/* * PicoSoC - A simple example SoC using PicoRV32 * * Copyright (C) 2017 Clifford Wolf * * 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. * */ 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 01300293; localparam [31:0] word1 = 32'h 00502223; 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 #50; flash_csb = 0; $display("-- BEGIN"); #50; end endtask task xfer_dummy; begin flash_io0_oe = 0; flash_io1_oe = 0; flash_io2_oe = 0; flash_io3_oe = 0; #50; flash_clk = 1; #50; flash_clk = 0; #50; end endtask task xfer_end; begin #50; flash_csb = 1; flash_io0_oe = 0; flash_io1_oe = 0; flash_io2_oe = 0; flash_io3_oe = 0; $display("-- END"); $display(""); #50; 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]; #50; rdata[7-i] = flash_io1; flash_clk <= 1; #50; flash_clk = 0; end $display("-- SPI SDR %02x %02x", data, rdata); #50; 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]; #50; flash_clk = 1; #50; flash_clk = 0; flash_io0_dout = data[0]; flash_io1_dout = data[1]; flash_io2_dout = data[2]; flash_io3_dout = data[3]; #50; flash_clk = 1; #50; flash_clk = 0; $display("-- QSPI SDR %02x --", data); #50; 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; #50; rdata[4] = flash_io0; rdata[5] = flash_io1; rdata[6] = flash_io2; rdata[7] = flash_io3; flash_clk <= 1; #50; flash_clk = 0; #50; rdata[0] = flash_io0; rdata[1] = flash_io1; rdata[2] = flash_io2; rdata[3] = flash_io3; flash_clk <= 1; #50; flash_clk = 0; $display("-- QSPI SDR -- %02x", rdata); #50; 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]; #50; flash_clk = 1; flash_io0_dout <= data[0]; flash_io1_dout <= data[1]; flash_io2_dout <= data[2]; flash_io3_dout <= data[3]; #50; flash_clk = 0; $display("-- QSPI DDR %02x --", data); #50; 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; #50; rdata[4] = flash_io0; rdata[5] = flash_io1; rdata[6] = flash_io2; rdata[7] = flash_io3; flash_clk <= 1; #50; rdata[0] = flash_io0; rdata[1] = flash_io1; rdata[2] = flash_io2; rdata[3] = flash_io3; flash_clk <= 0; $display("-- QSPI DDR -- %02x", rdata); #50; 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); 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); 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); 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); 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; #500; if (errcount) begin $display("FAIL"); $stop; end else begin $display("PASS"); end end endmodule