SPI interface design based on Verilog

The study of SPI interface circuit

1. Principle of SPI interface circuit

SPI, serial peripheral interface, is a synchronous serial interface technology introduced by Motorola. SPI bus is physically realized by the module called synchronous serial port on the micro processing control unit (MCU) connected to the peripheral micro controller (PICmicro). It allows MCU to carry out high-speed data communication with various peripheral devices in full duplex synchronous serial mode.

SPI is mainly used in EEPROM, Flash, RTC, ADC,
Between digital signal processor (DSP) and digital signal decoder. It only takes up four pins in the chip for control and data transmission, saving the number of pins in the chip, and saving space for PCB layout. Because of this simple and easy-to-use feature, more and more chips are integrated with SPI technology.

characteristic

① Master slave control mode is adopted:

  • SPI specifies that communication between two SPI devices must be controlled by Master to slave. One Master
    The device can control multiple Slave devices and SPI by providing Clock and selecting Slave devices
    The protocol also stipulates that the Slave device's Clock is provided to the Slave device by the Master device through the SCK pin
    The device itself cannot generate or control a Clock. If there is no Clock, the Slave device cannot work normally.

② Transfer data in synchronous mode:

  • The Master device will generate the corresponding clock pulse according to the data to be exchanged. The clock pulse constitutes the clock signal
    Clock signal controls when data exchange between two SPI devices and when to sample the received data through clock polarity (CPOL) and clock phase (CPHA),
    To ensure that data is transmitted synchronously between two devices.

③ Data exchanges:

  • The reason why the data transmission between SPI devices is also called data exchange is that the SPI protocol stipulates that an SPI device cannot only act as a "transmitter" or "receiver" in the process of data communication. In each Clock cycle, the SPI device will send and receive one
    Bit size data, equivalent to that the device has a bit size data to be exchanged.

    If a Slave device wants to receive the control signal from the Master, it must be able to be accessed by the Master device before that
    Therefore, the Master device must first select the Slave device through SS/CS pin, and select the Slave device to be accessed.

    In the process of data transmission, each received data must be sampled before the next data transmission. If the previously received data is not read,
    The received data may be discarded, resulting in the final failure of the SPI physical module. Therefore, in the program, it is usually after the SPI has transmitted the data,
    To read the data in SPI device, even if the data is useless in our program.

    **

Working mechanism:**

① Usually four signals of four wire SPI equipment:

Serial Clock is mainly used to transmit clock signal from Master device to Slave device, control the timing and rate of data exchange;

SS/CS, Slave Select/Chip Select, for Master device selection
Slave device, enabling the selected slave device to be accessed by the Master device;

SDO/MOSI, Serial Data Output/Master Out Slave In, also known as TX channel on the Master, is used as the data outlet, mainly for SPI equipment to send data;

SDI/MISO, Serial Data Input/Master In Slave Out, also known as
RX channel, as the data entry, is mainly used for SPI equipment to receive data.

② Two concepts: clock polarity and clock phase:

CPOL: clock polarity, indicating whether the clock signal is high level or low level when SPI is idle. If CPOL is set to 1, then the device is idle
The clock signal at the foot of SCK is high. When CPOL is set to 0, it is the opposite
CPOL = 0: SCK idle phase is low;
CPOL = 1: SCK idle phase is high;
CPHA: clock phase, which indicates whether the SPI device triggers data sampling when the clock signal on the SCK pin changes to the rising edge, or when the clock signal changes to the falling edge. If CPHA is set to 1, the SPI device triggers data sampling when the clock signal changes to the falling edge, and sends data when the rising edge. When CPHA is set to 0, it is the opposite

    CPHA = 0: Output data at negedge of clock while

receiving data at posedge of clock;

    CPHA = 1: Output data at posedge of clock

while receiving data at negedge of clock;

When configuring SPI interface clock on the master device side, it is necessary to make clear the clock requirements of the slave device, because the clock polarity and phase on the master device side are based on the slave device. Therefore, in the configuration of clock polarity, it must be clear whether the slave device receives data at the rising edge or the falling edge of the clock, and whether it outputs data at the falling edge or the rising edge of the clock. However, it should be noted that since the SDO of the master device is connected to the SDI of the slave device, the SDO of the slave device is connected to the SDI of the master device, the data received from the SDI of the slave device is sent from the SDO of the master device, and the data received from the SDI of the master device is sent from the SDO of the device, so the polarity configuration of the SPI clock on the master device (that is, the configuration of the SDO) is the opposite to that of the SDI of the slave device, The polarity of the data sent by the slave SDO is the same.

When the number of slaves increases, we can use the chip for auxiliary control.

③ Data transmission:

In one SPI clock cycle, the following operations are completed:

1) The host sends 1-bit data through the MOSI line, and the slave reads the 1-bit data through the line;

2) The slave sends 1-bit data through MISO line, and the host reads the 1-bit data through the line.

This is achieved by a shift register. As shown in the figure below, the master and slave have a shift register respectively, and they are connected into rings. With the clock pulse, the data is moved out of the master register and the slave register from the high to the low, and then into the slave register and the master register. When all the contents of the register are moved out, it is equivalent to the exchange of the contents of the two registers.

(4) Slave Slave implementation:

The signals at one end of SPI interface include strobe signal cs, serial input clock signal sclk, serial input data signal sdi and serial output data signal sdo. The other end is connected with the memory, and the signal at this end is the read-write control signal wr_rd, read-write address signal addr, write data parallel output signal dataout,
Read data parallel input signal datain.

Among the signals at one end of SPI interface, the serial input data signal sdi and the serial output data signal sdo can be multiplexed, that is, they share one signal SDIO, which is called three wire SPI interface. The following is the schematic waveform of the three wire SPI interface. In order to describe conveniently, we often use four wire SPI interface, that is, the signal at one end of SPI interface has four signal lines, including strobe signal cs, serial input clock signal sclk, serial input data signal sdi and serial output data signal sdo.


Write operation

Read operation

2. Simulation test

The software used this time is still Quartus. As we have learned about it in detail the previous week, we will not demonstrate the creation process of each step here, mainly focusing on the code implementation and the analysis of simulation results.

(1) It is assumed that the port signal at one end of SPI transmits 24 bit information in a transmission cycle, in which 16 bits are instruction information and 8 bits are data information. The first bit is 1 for write operation, otherwise it is read operation.


module spi (reset, cs, sclk, sdi, sdo,wr_rd, addr, rdata, wdata);
input     reset;
input           cs;
input          sclk;
input          sdi;
output        sdo;
output         wr_rd;
output  [14:0]  addr;
input   [7:0]   rdata;
output  [7:0]   wdata;
reg 	[ 2:0] cnt_bit;

always @(posedge sclk or negedge reset)

 
if (!reset)

cnt_bit <= 3'b0;
 
else if (!cs)
cnt_bit <= cnt_bit + 3'b1; 
else
  
cnt_bit <= 3'b0;

wire   cnt_full;

assign  	cnt_full = (cnt_bit==3'd7);

parameter IDLE    = 2'd0;   //Initial state

parameter INSTR_H = 2'd1;    //Status of high 8 bits in 16 bits of received instruction

parameter INSTR_L = 2'd2;    //Status of the lower 8 bits in the 16 bits of the received instruction

parameter DATA    = 2'd3;   //Transmit 8-bit data status

reg 	[ 1:0] current_state, next_state;

always @(posedge sclk or negedge reset)

  if (!reset)

   
current_state <= IDLE;

 
else if (cs)

   
current_state <= IDLE;

 
else

   
current_state <= next_state;

 

always @(*)

begin

 
case (current_state)

   
IDLE: begin

     
if (cs)

       
next_state = IDLE;

     
else

       
next_state = INSTR_H;

     
end

   
INSTR_H : begin

     
if (cnt_full)

       
next_state = INSTR_L;

     
else

       
next_state = INSTR_H;

     
end

   
INSTR_L : begin

     
if (cnt_full)

       
next_state = DATA;

     
else
next_state = INSTR_L
end
    DATA : begin     
if (cs)       
next_state = IDLE;
else       
next_state = DATA;
end   
default: next_state = IDLE;

endcase

end
reg 	[15:0] shift_reg_din;

always @(posedge sclk or negedge reset)
 
if (!reset)   
shift_reg_din <= 15'd0;

else if (cs)
shift_reg_din <= 15'd0;
else
  
shift_reg_din <= {shift_reg_din[14:0],sdi};

wire    cstate;
assign  	cstate = (current_state==INSTR_L);

reg     cnt_full_d, cstate_d;
always @(posedge sclk or negedge reset)

if (!reset) 
begin
cnt_full_d <= 0;

cstate_d <= 0;

end
else begin
   cnt_full_d <= cnt_full;
  
cstate_d <= cstate;

end

reg  	[14:0]  addr;

always @(negedge sclk or negedge reset)

 
if (!reset)
 
addr <= 15'd0; 
else if (cnt_full_d && cstate_d)//Indicates that the address has been read

   
addr <= shift_reg_din[14:0];//Assign 15 bit address to addr
else
  
addr <= addr;

reg               wr_rd;//Write is output relative to spi
always @(negedge sclk or negedge reset)

if (!reset)   
wr_rd <= 1'b0; 
else if (cnt_full_d && cstate_d)
  
wr_rd <= shift_reg_din[15];//After reading the address, assign the highest bit to write. If it is 1, it means write operation

reg  	[7:0]  wdata;

always @(posedge cs or negedge reset)

 
if (!reset)

   
wdata <= 8'd0;

 
else

   
wdata <= shift_reg_din[7:0];

 

reg  	[ 7:0] shift_reg_dout;

always @(negedge sclk or negedge reset)

 
if (!reset)

   
shift_reg_dout <= 8'b0;

 
else if ((cnt_bit==3'd0) && (current_state==DATA))

   
shift_reg_dout <= rdata;

 
else 

   
shift_reg_dout <= {shift_reg_dout[6:0],1'b0};//Serial output

assign sdo  = ((!wr_rd)&&(!cs)) ?
shift_reg_dout[7] : 1'b0;

endmodule


The test incentives are as follows:


module spi_tb();
reg    reset;
reg  cs  ;
reg  sclk;
reg  sdi  ;
wire sdo  ;
reg   [7:0]   rdata;
wire    wr_rd ;
wire  	[14:0]  addr;
wire  [7:0]   wdata;

spi u0(reset, cs, sclk, sdi, sdo, wr_rd,addr, rdata, wdata);

always  
 #5sclk=~sclk;

initial begin   

sclk = 0;

reset=0; 

cs = 1;

sdi = 0;

rdata=8'b00001111;

#27 reset=1;

#14 cs = 0;

sdi = 1;   
//Write operation

repeat(1) @(negedge sclk);

sdi = 0;

repeat(11) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(1) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(2) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(1) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(1) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(1) @(negedge sclk);

sdi = 1;

#11 cs = 1;

//-------The above completes a write transfer operation---------

 

repeat(5) @(negedge sclk);

cs = 0;

sdi = 0;   
//Read operation

repeat(1) @(negedge sclk);

sdi = 0;

repeat(11) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(1) @(negedge sclk);

sdi = 1;

repeat(1) @(negedge sclk);

sdi = 0;

repeat(1) @(negedge sclk);

sdi = 1'bz;
repeat(7) @(negedge sclk);
#11 cs = 1;
//-------The above completes a read transfer operation---------
#200 
$stop;


Simulation results:

Posted on Fri, 12 Jun 2020 06:12:46 -0400 by smclay