Messages Exchange with FPGA as Slave
The implementation builds onto the Byte Module code shown earlier. We will start by explaining how to pass multidimensional arrays through ports.
On Altera, we can the multidimentional arrays available in system verilog HDL
wire [nrRWregs+nrROregs-1:0] [31:0] registers;
The implementation is slightly more complicated on Xilinx, because Verilog 2001 doesn’t allow multidimensional arrays to be used as inputs or outputs. Instead, we work around this by flatten the 2D registers array into two vectors. One for input, and one for the output ports as shown in the code fragments below.
Flatten the 2-dimensional array,
registers, into vectors
genvar nn; wire [31:0] roRegs2D[0:nrROregs-1]; for ( nn = 0; nn < nrRWregs; nn = nn + 1) begin :nnRW assign rwRegs1D[32*nn+31:32*nn] = registers[nn]; // flatten end for ( nn = 0; nn < nrROregs; nn = nn + 1) begin :nnRO assign roRegs2D[nn] = roRegs1D[32*nn+31:32*nn]; // inflate end
Inflate the vectors,
roRegs1D, into a 2-dimensional array
wire [0:31] registers[0:nrRWregs+nrROregs-1]; genvar nn; for ( nn = 0; nn < nrRWregs; nn = nn + 1 ) begin :nnRW assign registers[nn] = rwRegs1D[32*nn+31:32*nn]; end for ( nn = 0; nn < nrROregs; nn = nn + 1 ) begin :nnRO assign roRegs1D[32*nn+31:32*nn] = registers[nn+nrRWregs]; end
The timing diagram below shows the relation between the different signals at the message level on Xilinx.
The Altera implementation is more optimized, as it needs to run at 200 MHz. The gate level simulation is shown below;
Finite State Machine
This message module converts the bytes into messages and visa versa. The protocol is implemented using a state machine with 4 states:
- Idle (0)
- Transmit status (1), transmits 8-bit status to master
- Transmit register value (2) , transmits a 32-bit register value to the master
- Receive register value (3), receives a 32-bit register value from the master
An additional state-like variable,
byteId, is used to keeps track of what byte to transmit or receive.
The complete project including constraints and test bench is available through Github. The two main files are listed below.
- SPI Slave, main module,
spi_msg.svon Altera (or
- SPI Slave, message interface,
spi_msg_if.svon Altera (or
To verify the implementation, run the test bench (
spi_msg_tb.v) using gate level simulation. This test bench will monitor the communication and report errors when found. In the real world, we connect the Arduino SPI Master that acts just like the test bench.
The next part explains how to proceed using this SPI message protocol.