从机模块slave_spi.v连接有ram,模拟CA T25010芯片存储数据,用rden,wren,data,address 进行通信,CAT25010芯片具体通信协议可参考起使用说明。
module slave_spi(clk,rst,cs,sck,si,so,rden,wren,data,address,data_send);input clk,rst,cs,sck;input si;input [7:0] data_send; //读取外部ram的数据,用于发送output rden,wren;output [7:0] data; //写入外部ram的数据output [7:0] address; //写入外部ram的数据的地址output so;reg rden,wren;reg [7:0] data;reg [7:0] address;reg [7:0] data_in;reg [7:0] addr_in;reg [7:0] data_send_buff;reg so_buff,link_so;reg [4:0] s_state;reg [3:0] read_state;reg [7:0] opecode;reg [3:0] readin_bit;wire so;assign so = link_so? so_buff:1'bz;parameter read_code=8'b0000_0011,write_code=8'b0000_0010;parameter idle=5'b00001,s_opecode=5'b00010,s_address=5'b00100,s_write=5'b01000,s_read=5'b10000;parameter bit7=4'b0010,bit6=4'b0011,bit5=4'b0100,bit4=4'b0101,bit3=4'b0110,bit2=4'b0111,bit1=4'b1000,bit0=4'b1001,bit_end=4'b1010;//提取上升沿的寄存器wire neg_cs,pos_cs;wire neg_sck,pos_sck;reg sck_temp1,sck_temp2;reg cs_temp1,cs_temp2;//提取CS和ack的上升沿河下降沿always @(posedge clk or negedge rst) beginif(!rst)beginsck_temp1<=0;sck_temp2<=0;//sck_temp3<=0;cs_temp1<=1;cs_temp2<=1;//cs_temp3<=1;endelsebeginsck_temp1<=sck;sck_temp2<=sck_temp1;//sck_temp3<=sck_temp2;cs_temp1<=cs;cs_temp2<=cs_temp1;//cs_temp3<=cs_temp2;endendassign neg_cs = ~cs_temp1&cs_temp2; assign pos_cs = cs_temp1&~cs_temp2; assign neg_sck = ~sck_temp1&sck_temp2; assign pos_sck = sck_temp1&~sck_temp2;always @(posedge clk or negedge rst) beginif(!rst)beginso_buff<=0;link_so<=0;rden<=0;wren<=0;data<=0;address<=0;data_in<=0;addr_in<=0;s_state<=idle;read_state<=bit7;opecode<=0;readin_bit<=0;endelsebeginif(pos_cs)beginso_buff<=0;link_so<=0;rden<=0;wren<=0;data<=0;address<=0;data_in<=0;addr_in<=0;s_state<=idle;read_state<=bit7;opecode<=0;readin_bit<=0;endelsebegincase(s_state)idle:beginif(neg_cs)s_state<=s_opecode;elsebegins_state<=idle;endends_opecode:beginif(pos_sck)beginopecode<={opecode[6:0],si};readin_bit<=readin_bit+1'b1;endelsebeginif(readin_bit==8)beginreadin_bit<=0;if(opecode==read_code||opecode==write_code)begins_state<=s_address;endelses_state<=idle;endendends_address:beginif(pos_sck)beginreadin_bit<=readin_bit+1'b1;addr_in<={addr_in[6:0],si};endelsebeginif(readin_bit==8)beginreadin_bit<=0;if(opecode==write_code)begins_state<=s_write;address<=addr_in;endelsebegins_state<=s_read;address<=addr_in;rden<=1;///////endendendends_write:beginif(pos_sck)beginreadin_bit<=readin_bit+1'b1;data_in<={data_in[6:0],si};endelsebeginif(readin_bit==8)begindata<=data_in;//??????wren<=1;if(neg_sck)begin//??????wren<=0;//??????readin_bit<=0;endendendends_read: read8bit;default: s_state<=idle;endcaseendendendtask read8bit;begincase(read_state)bit7:beginif(neg_sck)beginrden<=0;link_so<=1;so_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit6;endelsebegindata_send_buff<=data_send;read_state<=bit7;endendbit6:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit5;endelseread_state<=bit6;endbit5:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit4;endelseread_state<=bit5;endbit4:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit3;endelseread_state<=bit4;bit3:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit2;endelseread_state<=bit3;endbit2:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit1;endelseread_state<=bit2;endbit1:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit0;endelseread_state<=bit1;endbit0:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit_end;endelseread_state<=bit0;bit_end:beginif(neg_sck)beginlink_so<=0;endelseread_state<=bit_end;enddefault: read_state<=bit7;endcaseendendtaskendmodule测试仿真文件`timescale 1ms/1ms`define halfperiod 10module top;reg cs,rst,clk;reg si,sck;reg [7:0] cnt;reg [7:0] data_send;reg [7:0] rd_code;reg [7:0] wr_code;reg [7:0] addr;reg [7:0] mdata;//reg [7:0]wire [7:0] data;wire [7:0] address;always #(`halfperiod) clk=~clk;initialbegincs=1;cnt=0;rst=1;clk=1;rd_code=8'b0000_0011;wr_code=8'b0000_0010;addr=100;mdata=200;data_send=50;#15 rst=0;#30 rst=1;//#1000 cs=1;//#4000 $stop;repeat(10)begin#500 cs=0;si=wr_code[7];@(negedge sck) si=wr_code[6]; @(negedge sck) si=wr_code[5]; @(negedge sck) si=wr_code[4]; @(negedge sck) si=wr_code[3]; @(negedge sck) si=wr_code[2]; @(negedge sck) si=wr_code[1]; @(negedge sck) si=wr_code[0];@(negedge sck) si=addr[7];@(negedge sck) si=addr[6];@(negedge sck) si=addr[5];@(negedge sck) si=addr[4];@(negedge sck) si=addr[3];@(negedge sck) si=addr[2];@(negedge sck) si=addr[1];@(negedge sck) si=addr[0]; addr=addr+1;@(negedge sck) si=mdata[7]; @(negedge sck) si=mdata[6]; @(negedge sck) si=mdata[5]; @(negedge sck) si=mdata[4]; @(negedge sck) si=mdata[3]; @(negedge sck) si=mdata[2]; @(negedge sck) si=mdata[1]; @(negedge sck) si=mdata[0]; mdata=mdata+1;@(negedge sck) si=1'bz;#800 cs=1;endrepeat(10)begin#1000 cs=0;si=rd_code[7];@(negedge sck) si=rd_code[6];@(negedge sck) si=rd_code[5];@(negedge sck) si=rd_code[4];@(negedge sck) si=rd_code[3];@(negedge sck) si=rd_code[2];@(negedge sck) si=rd_code[1];@(negedge sck) si=rd_code[0];@(negedge sck) si=addr[7];@(negedge sck) si=addr[6];@(negedge sck) si=addr[5];@(negedge sck) si=addr[4];@(negedge sck) si=addr[3];@(negedge sck) si=addr[2];@(negedge sck) si=addr[1];@(negedge sck) si=addr[0];addr=addr+1;@(negedge sck) si=1'bz;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;data_send=data_send+1;@(negedge sck) si=1'bz;#800 cs=1;end#1000 $stop;endalways @(posedge clk)beginif(cs==0)beginif(cnt==8'b0011_0010) //50beginsck=~sck;cnt=0;endelsecnt=cnt+1;endelsecnt=0;endslave_spi ss(clk,rst,cs,sck,si,so,rden,wren,data,address,data_send); endmodule。