summaryrefslogtreecommitdiffstats
path: root/picosoc/spiflash_tb.v
diff options
context:
space:
mode:
Diffstat (limited to 'picosoc/spiflash_tb.v')
-rw-r--r--picosoc/spiflash_tb.v366
1 files changed, 366 insertions, 0 deletions
diff --git a/picosoc/spiflash_tb.v b/picosoc/spiflash_tb.v
new file mode 100644
index 0000000..a5b5edc
--- /dev/null
+++ b/picosoc/spiflash_tb.v
@@ -0,0 +1,366 @@
+/*
+ * PicoSoC - A simple example SoC using PicoRV32
+ *
+ * Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
+ *
+ * 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