picorv32/picosoc/spiflash_tb.v

367 lines
7.6 KiB
Verilog

/*
* PicoSoC - A simple example SoC using PicoRV32
*
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
`timescale 1 ns / 1 ps
module testbench;
reg flash_csb = 1;
reg flash_clk = 0;
wire flash_io0;
wire flash_io1;
wire flash_io2;
wire flash_io3;
reg flash_io0_oe = 0;
reg flash_io1_oe = 0;
reg flash_io2_oe = 0;
reg flash_io3_oe = 0;
reg flash_io0_dout = 0;
reg flash_io1_dout = 0;
reg flash_io2_dout = 0;
reg flash_io3_dout = 0;
assign flash_io0 = flash_io0_oe ? flash_io0_dout : 1'bz;
assign flash_io1 = flash_io1_oe ? flash_io1_dout : 1'bz;
assign flash_io2 = flash_io2_oe ? flash_io2_dout : 1'bz;
assign flash_io3 = flash_io3_oe ? flash_io3_dout : 1'bz;
spiflash uut (
.csb(flash_csb),
.clk(flash_clk),
.io0(flash_io0),
.io1(flash_io1),
.io2(flash_io2),
.io3(flash_io3)
);
localparam [23:0] offset = 24'h100000;
localparam [31:0] word0 = 32'h 00000093;
localparam [31:0] word1 = 32'h 00000193;
reg [7:0] rdata;
integer errcount = 0;
task expect;
input [7:0] data;
begin
if (data !== rdata) begin
$display("ERROR: Got %x (%b) but expected %x (%b).", rdata, rdata, data, data);
errcount = errcount + 1;
end
end
endtask
task xfer_begin;
begin
#5;
flash_csb = 0;
$display("-- BEGIN");
#5;
end
endtask
task xfer_dummy;
begin
flash_io0_oe = 0;
flash_io1_oe = 0;
flash_io2_oe = 0;
flash_io3_oe = 0;
#5;
flash_clk = 1;
#5;
flash_clk = 0;
#5;
end
endtask
task xfer_end;
begin
#5;
flash_csb = 1;
flash_io0_oe = 0;
flash_io1_oe = 0;
flash_io2_oe = 0;
flash_io3_oe = 0;
$display("-- END");
$display("");
#5;
end
endtask
task xfer_spi;
input [7:0] data;
integer i;
begin
flash_io0_oe = 1;
flash_io1_oe = 0;
flash_io2_oe = 0;
flash_io3_oe = 0;
for (i = 0; i < 8; i=i+1) begin
flash_io0_dout = data[7-i];
#5;
flash_clk = 1;
rdata[7-i] = flash_io1;
#5;
flash_clk = 0;
end
$display("-- SPI SDR %02x %02x", data, rdata);
#5;
end
endtask
task xfer_qspi_wr;
input [7:0] data;
integer i;
begin
flash_io0_oe = 1;
flash_io1_oe = 1;
flash_io2_oe = 1;
flash_io3_oe = 1;
flash_io0_dout = data[4];
flash_io1_dout = data[5];
flash_io2_dout = data[6];
flash_io3_dout = data[7];
#5;
flash_clk = 1;
#5;
flash_clk = 0;
flash_io0_dout = data[0];
flash_io1_dout = data[1];
flash_io2_dout = data[2];
flash_io3_dout = data[3];
#5;
flash_clk = 1;
#5;
flash_clk = 0;
$display("-- QSPI SDR %02x --", data);
#5;
end
endtask
task xfer_qspi_rd;
integer i;
begin
flash_io0_oe = 0;
flash_io1_oe = 0;
flash_io2_oe = 0;
flash_io3_oe = 0;
#5;
flash_clk = 1;
rdata[4] = flash_io0;
rdata[5] = flash_io1;
rdata[6] = flash_io2;
rdata[7] = flash_io3;
#5;
flash_clk = 0;
#5;
flash_clk = 1;
rdata[0] = flash_io0;
rdata[1] = flash_io1;
rdata[2] = flash_io2;
rdata[3] = flash_io3;
#5;
flash_clk = 0;
$display("-- QSPI SDR -- %02x", rdata);
#5;
end
endtask
task xfer_qspi_ddr_wr;
input [7:0] data;
integer i;
begin
flash_io0_oe = 1;
flash_io1_oe = 1;
flash_io2_oe = 1;
flash_io3_oe = 1;
flash_io0_dout = data[4];
flash_io1_dout = data[5];
flash_io2_dout = data[6];
flash_io3_dout = data[7];
#5;
flash_clk = 1;
flash_io0_dout = data[0];
flash_io1_dout = data[1];
flash_io2_dout = data[2];
flash_io3_dout = data[3];
#5;
flash_clk = 0;
$display("-- QSPI DDR %02x --", data);
#5;
end
endtask
task xfer_qspi_ddr_rd;
integer i;
begin
flash_io0_oe = 0;
flash_io1_oe = 0;
flash_io2_oe = 0;
flash_io3_oe = 0;
#5;
flash_clk = 1;
rdata[4] = flash_io0;
rdata[5] = flash_io1;
rdata[6] = flash_io2;
rdata[7] = flash_io3;
#5;
flash_clk = 0;
rdata[0] = flash_io0;
rdata[1] = flash_io1;
rdata[2] = flash_io2;
rdata[3] = flash_io3;
$display("-- QSPI DDR -- %02x", rdata);
#5;
end
endtask
initial begin
$dumpfile("spiflash_tb.vcd");
$dumpvars(0, testbench);
$display("");
$display("Reset (FFh)");
xfer_begin;
xfer_spi(8'h ff);
xfer_end;
$display("Power Up (ABh)");
xfer_begin;
xfer_spi(8'h ab);
xfer_end;
$display("Read Data (03h)");
xfer_begin;
xfer_spi(8'h 03);
xfer_spi(offset[23:16]);
xfer_spi(offset[15:8]);
xfer_spi(offset[7:0]);
xfer_spi(8'h 00); expect(word0[7:0]);
xfer_spi(8'h 00); expect(word0[15:8]);
xfer_spi(8'h 00); expect(word0[23:16]);
xfer_spi(8'h 00); expect(word0[31:24]);
xfer_spi(8'h 00); expect(word1[7:0]);
xfer_spi(8'h 00); expect(word1[15:8]);
xfer_spi(8'h 00); expect(word1[23:16]);
xfer_spi(8'h 00); expect(word1[31:24]);
xfer_end;
$display("Quad I/O Read (EBh)");
xfer_begin;
xfer_spi(8'h eb);
xfer_qspi_wr(offset[23:16]);
xfer_qspi_wr(offset[15:8]);
xfer_qspi_wr(offset[7:0]);
xfer_qspi_wr(8'h a5);
repeat (8) xfer_dummy;
xfer_qspi_rd; expect(word0[7:0]);
xfer_qspi_rd; expect(word0[15:8]);
xfer_qspi_rd; expect(word0[23:16]);
xfer_qspi_rd; expect(word0[31:24]);
xfer_qspi_rd; expect(word1[7:0]);
xfer_qspi_rd; expect(word1[15:8]);
xfer_qspi_rd; expect(word1[23:16]);
xfer_qspi_rd; expect(word1[31:24]);
xfer_end;
$display("Continous Quad I/O Read");
xfer_begin;
xfer_qspi_wr(offset[23:16]);
xfer_qspi_wr(offset[15:8]);
xfer_qspi_wr(offset[7:0]);
xfer_qspi_wr(8'h ff);
repeat (8) xfer_dummy;
xfer_qspi_rd; expect(word0[7:0]);
xfer_qspi_rd; expect(word0[15:8]);
xfer_qspi_rd; expect(word0[23:16]);
xfer_qspi_rd; expect(word0[31:24]);
xfer_qspi_rd; expect(word1[7:0]);
xfer_qspi_rd; expect(word1[15:8]);
xfer_qspi_rd; expect(word1[23:16]);
xfer_qspi_rd; expect(word1[31:24]);
xfer_end;
$display("DDR Quad I/O Read (EDh)");
xfer_begin;
xfer_spi(8'h ed);
xfer_qspi_ddr_wr(offset[23:16]);
xfer_qspi_ddr_wr(offset[15:8]);
xfer_qspi_ddr_wr(offset[7:0]);
xfer_qspi_ddr_wr(8'h a5);
repeat (8) xfer_dummy;
xfer_qspi_ddr_rd; expect(word0[7:0]);
xfer_qspi_ddr_rd; expect(word0[15:8]);
xfer_qspi_ddr_rd; expect(word0[23:16]);
xfer_qspi_ddr_rd; expect(word0[31:24]);
xfer_qspi_ddr_rd; expect(word1[7:0]);
xfer_qspi_ddr_rd; expect(word1[15:8]);
xfer_qspi_ddr_rd; expect(word1[23:16]);
xfer_qspi_ddr_rd; expect(word1[31:24]);
xfer_end;
$display("Continous DDR Quad I/O Read");
xfer_begin;
xfer_qspi_ddr_wr(offset[23:16]);
xfer_qspi_ddr_wr(offset[15:8]);
xfer_qspi_ddr_wr(offset[7:0]);
xfer_qspi_ddr_wr(8'h ff);
repeat (8) xfer_dummy;
xfer_qspi_ddr_rd; expect(word0[7:0]);
xfer_qspi_ddr_rd; expect(word0[15:8]);
xfer_qspi_ddr_rd; expect(word0[23:16]);
xfer_qspi_ddr_rd; expect(word0[31:24]);
xfer_qspi_ddr_rd; expect(word1[7:0]);
xfer_qspi_ddr_rd; expect(word1[15:8]);
xfer_qspi_ddr_rd; expect(word1[23:16]);
xfer_qspi_ddr_rd; expect(word1[31:24]);
xfer_end;
#5;
if (errcount) begin
$display("FAIL");
$stop;
end else begin
$display("PASS");
end
end
endmodule