Skip to content

Commit

Permalink
Update SPI Testbench to support multiple read / write demands (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
IveanEx committed Nov 2, 2024
1 parent 241c381 commit 15a0f00
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 42 deletions.
119 changes: 79 additions & 40 deletions target/rtl/test/spi_tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,9 @@
`define SEEK_CUR 1
`define SEEK_END 2

task automatic spi_read(input logic [31:0] addr, input integer length);
// Inputs:
// addr - 32-bit Address to read from
// length - Number of bytes to read
// Output:
// data - Array to store read data

reg [7:0] cmd; // SPI read command code
integer i, j, k;
reg [3:0] mosi_data; // Data to send over SPI (master out)
reg [3:0] miso_data; // Data received from SPI (slave out)
task automatic spi_init();
reg [7:0] cmd; // SPI command code
integer i;

// Wait for a clock edge to align
@(posedge spis_sck_i);
Expand All @@ -32,7 +24,22 @@ task automatic spi_read(input logic [31:0] addr, input integer length);

@(posedge spis_sck_i);
spis_csb_i = 1; // Bring CSB high to end the transaction
#1us; // Wait for a clock edge to align

endtask

task automatic spi_read(input integer length, input logic [31:0] addr);
// Inputs:
// addr - 32-bit Address to read from
// length - Number of bytes to read
// Output:
// data - Array to store read data

reg [7:0] cmd; // SPI read command code
integer i, j, k;
reg [3:0] mosi_data; // Data to send over SPI (master out)
reg [3:0] miso_data; // Data received from SPI (slave out)

// Wait for a clock edge to align
@(posedge spis_sck_i);
spis_csb_i = 0; // Bring CSB high to end the transaction

Expand Down Expand Up @@ -102,39 +109,80 @@ task automatic spi_read(input logic [31:0] addr, input integer length);
spis_csb_i = 1;
endtask

task automatic spi_read_u32(input logic [31:0] addr);
spi_read(4, addr);
endtask

task automatic spi_write(input string path, input logic [31:0] addr);
task automatic spi_write_u32(input logic [31:0] data, input logic [31:0] addr);
// Inputs:
// path - Path to the file to write
// addr - 32-bit Address to read from
// data - 8-bit data to write
// addr - 32-bit Address to write to

reg [7:0] cmd; // SPI write command code
integer i, j, k;
integer i, j;
reg [3:0] mosi_data; // Data to send over SPI (master out)
reg [3:0] miso_data; // Data received from SPI (slave out)
integer file;
integer file_size;

// Start to load binaries from file
// Wait for a clock edge to align
@(posedge spis_sck_i);
spis_csb_i = 0;
spis_csb_i = 0; // Bring CSB high to end the transaction

// Switch SPI to Quad SPI mode
cmd = 8'h1;
for (i = 7; i >= 0; i--) begin
// Set the SPI Write MEM code
cmd = 8'h2;

// Send the command code (8 bits) over 4 data lines (2 clock cycles)
for (i = 7; i >= 0; i -= 4) begin
@(negedge spis_sck_i);
spis_sd_i[0] = cmd[i]; // Send 1 bit at a time on MOSI
if (i >= 3) begin
mosi_data = cmd[i-:4];
end else begin
// For i = 3 to 0
mosi_data = cmd[3:0];
mosi_data = mosi_data << (3 - i); // Left-align to 4 bits
end
spis_sd_i = mosi_data; // Drive data lines
end
// Enable Quad SPI mode by writing 0x01 to the status register
for (i = 7; i >= 0; i--) begin

// Send the 32-bit address over 4 data lines (8 clock cycles)
for (i = 31; i >= 0; i -= 4) begin
@(negedge spis_sck_i);
spis_sd_i[0] = cmd[i]; // Send 1 bit at a time on MOSI
if (i >= 3) begin
mosi_data = addr[i-:4];
end else begin
// For i = 3 to 0
mosi_data = addr[3:0];
mosi_data = mosi_data << (3 - i); // Left-align to 4 bits
end
spis_sd_i = mosi_data; // Drive data lines
end

@(posedge spis_sck_i);
spis_csb_i = 1; // Bring CSB high to end the transaction
#1us; // Wait for a clock edge to align
// Send the 32-bit data over 4 data lines (8 clock cycles)
for (i = 31; i >= 0; i -= 4) begin
@(negedge spis_sck_i);
mosi_data = data[i-:4];
spis_sd_i = mosi_data; // Drive data lines

end
$display("Wrote to address %h finished", addr);
@(negedge spis_sck_i);

// Bring CSB high to end the transaction
spis_csb_i = 1;
endtask

task automatic spi_write_image(input string path, input logic [31:0] addr);
// Inputs:
// path - Path to the file to write
// addr - 32-bit Address to read from

reg [7:0] cmd; // SPI write command code
integer i, j, k;
reg [3:0] mosi_data; // Data to send over SPI (master out)
reg [3:0] miso_data; // Data received from SPI (slave out)
integer file;
integer file_size;

// Start to load binaries from file
// Wait for a clock edge to align
@(posedge spis_sck_i);
spis_csb_i = 0; // Bring CSB high to end the transaction

Expand Down Expand Up @@ -167,15 +215,6 @@ task automatic spi_write(input string path, input logic [31:0] addr);
spis_sd_i = mosi_data; // Drive data lines
end

// @(negedge spis_sck_i); // Wait for last data to be sent

// Insert dummy cycles if required (e.g., 32 cycles)
// Write process seems not need dummy cycles
// for (i = 0; i <= 32; i = i + 1) begin
// @(posedge spis_sck_i);
// // Do nothing, just wait
// end

// Now write the data to the slave
// Open the file for reading and get the size of the file
file = $fopen(path, "r");
Expand Down
15 changes: 13 additions & 2 deletions target/rtl/test/testharness.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,19 @@ module testharness import occamy_pkg::*; (
`include "spi_tb.sv"
initial begin
#10us;
// spi_read(32'h80000000, 128);
// spi_write("app.bin", 32'h80000000);
// spi_init();
// #1us;
// spi_read(128, 32'h80000000);
// #1us;
// spi_write_u32('0, 32'h80000300);
// #1us;
// spi_read_u32(32'h80000300);
// #1us;
// spi_write_u32(32'hABCDEF00, 32'h80000300);
// #1us;
// spi_read_u32(32'h80000300);
// #1us;
// spi_write_image("app.bin", 32'h80000000); #1us;
end
`endif

Expand Down

0 comments on commit 15a0f00

Please sign in to comment.