2017-08-05 11:08:16 -04:00
|
|
|
/*
|
2017-08-07 07:38:07 -04:00
|
|
|
* PicoSoC - A simple example SoC using PicoRV32
|
2017-08-05 11:08:16 -04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
`timescale 1 ns / 1 ps
|
|
|
|
|
2017-08-05 11:08:16 -04:00
|
|
|
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;
|
2018-05-11 16:56:52 -04:00
|
|
|
localparam [31:0] word0 = 32'h 00000093;
|
|
|
|
localparam [31:0] word1 = 32'h 00000193;
|
2017-08-05 11:08:16 -04:00
|
|
|
|
|
|
|
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
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_csb = 0;
|
|
|
|
$display("-- BEGIN");
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
end
|
|
|
|
endtask
|
|
|
|
|
|
|
|
task xfer_dummy;
|
|
|
|
begin
|
|
|
|
flash_io0_oe = 0;
|
|
|
|
flash_io1_oe = 0;
|
|
|
|
flash_io2_oe = 0;
|
|
|
|
flash_io3_oe = 0;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 1;
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 0;
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
end
|
|
|
|
endtask
|
|
|
|
|
|
|
|
task xfer_end;
|
|
|
|
begin
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_csb = 1;
|
|
|
|
flash_io0_oe = 0;
|
|
|
|
flash_io1_oe = 0;
|
|
|
|
flash_io2_oe = 0;
|
|
|
|
flash_io3_oe = 0;
|
|
|
|
$display("-- END");
|
|
|
|
$display("");
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
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];
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
|
|
|
flash_clk = 1;
|
2017-08-05 11:08:16 -04:00
|
|
|
rdata[7-i] = flash_io1;
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
$display("-- SPI SDR %02x %02x", data, rdata);
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
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];
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 1;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
|
|
|
flash_clk = 0;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_io0_dout = data[0];
|
|
|
|
flash_io1_dout = data[1];
|
|
|
|
flash_io2_dout = data[2];
|
|
|
|
flash_io3_dout = data[3];
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 1;
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 0;
|
|
|
|
|
|
|
|
$display("-- QSPI SDR %02x --", data);
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
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;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
|
|
|
flash_clk = 1;
|
2017-08-05 11:08:16 -04:00
|
|
|
rdata[4] = flash_io0;
|
|
|
|
rdata[5] = flash_io1;
|
|
|
|
rdata[6] = flash_io2;
|
|
|
|
rdata[7] = flash_io3;
|
2017-08-07 10:27:57 -04:00
|
|
|
|
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 0;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
|
|
|
flash_clk = 1;
|
2017-08-05 11:08:16 -04:00
|
|
|
rdata[0] = flash_io0;
|
|
|
|
rdata[1] = flash_io1;
|
|
|
|
rdata[2] = flash_io2;
|
|
|
|
rdata[3] = flash_io3;
|
2017-08-07 10:27:57 -04:00
|
|
|
|
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 0;
|
|
|
|
|
|
|
|
$display("-- QSPI SDR -- %02x", rdata);
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
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;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
flash_io0_dout = data[4];
|
|
|
|
flash_io1_dout = data[5];
|
|
|
|
flash_io2_dout = data[6];
|
|
|
|
flash_io3_dout = data[7];
|
2017-08-05 11:08:16 -04:00
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 1;
|
2017-08-07 10:27:57 -04:00
|
|
|
flash_io0_dout = data[0];
|
|
|
|
flash_io1_dout = data[1];
|
|
|
|
flash_io2_dout = data[2];
|
|
|
|
flash_io3_dout = data[3];
|
2017-08-05 11:08:16 -04:00
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
flash_clk = 0;
|
|
|
|
|
|
|
|
$display("-- QSPI DDR %02x --", data);
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
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;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
|
|
|
flash_clk = 1;
|
2017-08-05 11:08:16 -04:00
|
|
|
rdata[4] = flash_io0;
|
|
|
|
rdata[5] = flash_io1;
|
|
|
|
rdata[6] = flash_io2;
|
|
|
|
rdata[7] = flash_io3;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
|
|
|
flash_clk = 0;
|
2017-08-05 11:08:16 -04:00
|
|
|
rdata[0] = flash_io0;
|
|
|
|
rdata[1] = flash_io1;
|
|
|
|
rdata[2] = flash_io2;
|
|
|
|
rdata[3] = flash_io3;
|
|
|
|
|
|
|
|
$display("-- QSPI DDR -- %02x", rdata);
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
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);
|
2018-05-11 16:56:52 -04:00
|
|
|
repeat (8) xfer_dummy;
|
2017-08-05 11:08:16 -04:00
|
|
|
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);
|
2018-05-11 16:56:52 -04:00
|
|
|
repeat (8) xfer_dummy;
|
2017-08-05 11:08:16 -04:00
|
|
|
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);
|
2018-05-11 16:56:52 -04:00
|
|
|
repeat (8) xfer_dummy;
|
2017-08-05 11:08:16 -04:00
|
|
|
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);
|
2018-05-11 16:56:52 -04:00
|
|
|
repeat (8) xfer_dummy;
|
2017-08-05 11:08:16 -04:00
|
|
|
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;
|
|
|
|
|
2017-08-07 10:27:57 -04:00
|
|
|
#5;
|
2017-08-05 11:08:16 -04:00
|
|
|
|
|
|
|
if (errcount) begin
|
|
|
|
$display("FAIL");
|
|
|
|
$stop;
|
|
|
|
end else begin
|
|
|
|
$display("PASS");
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endmodule
|