Verilog设计SPI slave 一些问题
时间:10-02
整理:3721RD
点击:


请问如何按照这个要求用Verilog来设计该SPI slave,网上有关基本找不到相关的SPI slave参考代码
主要存在这几个疑问:1、SPI从机除了主机发过来的同步时钟SCLK外,是否还需要另外一个输入时钟?我看见网上有关的从机代码都增加了clk,而且是用这个clk来检测SCLK的上升沿和下降沿,我的疑问是从机不就是直接用posedge SCLK就可以是实现检测到上升沿了吗?
代码如下:
- module SPI_Slave(
- clk, //system clock 50MHz
- SCK, SSEL, MOSI,MISO//SPI communication pin
- );
- input SCK, SSEL, MOSI;
- output MISO;
-
- // sync SCK to the FPGA clock using a 3-bits shift register
- reg [2:0] SCKr;
- always @(posedge clk) SCKr <= {SCKr[1:0], SCK};
- wire SCK_risingedge = (SCKr[2:1]==2'b01); // now we can detect SCK rising edges
- wire SCK_fallingedge = (SCKr[2:1]==2'b10); // and falling edges
- // same thing for SSEL
- reg [2:0] SSELr;
- always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
- wire SSEL_active = ~SSELr[1]; // SSEL is active low
- wire SSEL_startmessage = (SSELr[2:1]==2'b10); // message starts at falling edge
- wire SSEL_endmessage = (SSELr[2:1]==2'b01); // message stops at rising edge
- // and for MOSI
- reg [1:0] MOSIr;
- always @(posedge clk) MOSIr <= {MOSIr[0], MOSI};
- wire MOSI_data = MOSIr[1];
- reg [2:0] bitcnt; // we handle SPI in 8-bits format, so we need a 3 bits counter to count the bits as they come in
- //-------------------receive data-------------------------------------------------
- reg byte_received; // high when a byte has been received
- reg [7:0] byte_data_received,rev_data;
- reg [7:0] byte_data_sent,sent_data;
- always @(posedge clk)
- begin
- if( SSEL_active )
- begin
- if(SSEL_startmessage)
- byte_data_sent <= sent_data;
- end
- if(~SSEL_active)
- begin
- bitcnt <= 3'b000;
- byte_data_sent <= 8'h00; // after that, we send 0s///////////
- end
- else
- if(SCK_risingedge)
- begin
- bitcnt <= bitcnt + 3'b001;
- byte_data_received <= {byte_data_received[6:0], MOSI_data}; // implement a shift-left
- //register (since we receive the data MSB first)
- byte_data_sent <= {byte_data_sent[6:0], 1'b0};///////////
- end
- end
- always @(posedge clk) byte_received <= SSEL_active && SCK_risingedge && (bitcnt==3'b111);
- //-----------------------receive data---------------------
- always @(posedge clk)
- if(byte_received)
- begin
- rev_data <= byte_data_received;
- end
- //-----------------------send data----------------------
- assign MISO = byte_data_sent[7]; // send MSB first
- endmodule
2、怎么区分接收的是数据还是地址?
3、由于首字节定义了通信模式和地址,刚开始时是怎么检测读写使能及地址的,是接收一位用一个状态机吗,然后用八个状态,还是用计数器来检测?
4、当接收完地址0时时怎么转换到读数据或者写数据操作,如果在片选信号一直使能的情况下这个转换状态肯定要用到一个时钟沿,那么这时数据传输的连贯性不就会被破坏了吗?
实在搞不懂,望同行们提供一些宝贵意见,万分感谢!
SPI指负责每个SCLK传one bit data,什么时候发有效数据,有效数据的含义都是自己定的,一般MASTER是别人提供的,肯定是软件来操作的,写软件的时候,看怎么安排有效数据,slave是你自己的,软件怎么安排数据,你就怎么检查,恢复有效数据。
那也就是说slave 这边要实现读写使能检测、寻址的操作吗?但是我看见的SPI 接口Verilog代码,不管是master或者slave,好像读写使能是直接外部输入的,而且也没有寻址这个功能,只是使用两个八位移位寄存器简单实现数据的交换,所以看到这个技术手册就无从下手了,请问您有什么好的思路吗
这个很简单
串并转换+译码器就可以搞定了
第一个问题,通信时钟和系统时钟不一致,也就是双时钟情况下,为了避免异步时钟的问题,一般都用系统始终去采集信号时钟。尤其是一般的接口信号,时钟频率都很低,所以更是建议如此。 再说详细点,时钟是一个扇出的信号,需要接很多的寄存器,所以布局布线需要单独处理时钟。所以设计中尽量采用单一时钟,可以简化后续工作,稳定整个系统。
地址和数据的判断就是一个状态机。每接收8位,进行一次判断。状态机一开始是地址接收,根据读写位来判断下个状态是读还是写。状态机写好,基本上你所有的问题就都解决了。
用来读写数据的,也就是和MCU通讯。
