summaryrefslogtreecommitdiffstats
path: root/testbench_wb.v
diff options
context:
space:
mode:
Diffstat (limited to 'testbench_wb.v')
-rw-r--r--testbench_wb.v293
1 files changed, 293 insertions, 0 deletions
diff --git a/testbench_wb.v b/testbench_wb.v
new file mode 100644
index 0000000..4e1a8eb
--- /dev/null
+++ b/testbench_wb.v
@@ -0,0 +1,293 @@
+`timescale 1 ns / 1 ps
+
+`ifndef VERILATOR
+module testbench #(
+ parameter VERBOSE = 0
+);
+ reg clk = 1;
+ reg resetn = 1;
+ wire trap;
+
+ always #5 clk = ~clk;
+
+ initial begin
+ repeat (100) @(posedge clk);
+ resetn <= 0;
+ end
+
+ initial begin
+ if ($test$plusargs("vcd")) begin
+ $dumpfile("testbench.vcd");
+ $dumpvars(0, testbench);
+ end
+ repeat (1000000) @(posedge clk);
+ $display("TIMEOUT");
+ $finish;
+ end
+
+ wire trace_valid;
+ wire [35:0] trace_data;
+ integer trace_file;
+
+ initial begin
+ if ($test$plusargs("trace")) begin
+ trace_file = $fopen("testbench.trace", "w");
+ repeat (10) @(posedge clk);
+ while (!trap) begin
+ @(posedge clk);
+ if (trace_valid)
+ $fwrite(trace_file, "%x\n", trace_data);
+ end
+ $fclose(trace_file);
+ $display("Finished writing testbench.trace.");
+ end
+ end
+
+ picorv32_wrapper #(
+ .VERBOSE (VERBOSE)
+ ) top (
+ .wb_clk(clk),
+ .wb_rst(resetn),
+ .trap(trap),
+ .trace_valid(trace_valid),
+ .trace_data(trace_data)
+ );
+endmodule
+`endif
+
+module picorv32_wrapper #(
+ parameter VERBOSE = 0
+) (
+ input wb_clk,
+ input wb_rst,
+ output trap,
+ output trace_valid,
+ output [35:0] trace_data
+);
+ wire tests_passed;
+ reg [31:0] irq = 0;
+ wire mem_instr;
+
+ reg [15:0] count_cycle = 0;
+ always @(posedge wb_clk) count_cycle <= !wb_rst ? count_cycle + 1 : 0;
+
+ always @* begin
+ irq = 0;
+ irq[4] = &count_cycle[12:0];
+ irq[5] = &count_cycle[15:0];
+ end
+
+ wire [31:0] wb_m2s_adr;
+ wire [31:0] wb_m2s_dat;
+ wire [3:0] wb_m2s_sel;
+ wire wb_m2s_we;
+ wire wb_m2s_cyc;
+ wire wb_m2s_stb;
+ wire [31:0] wb_s2m_dat;
+ wire wb_s2m_ack;
+
+ wb_ram #(
+ .depth (128*1024),
+ .VERBOSE (VERBOSE)
+ ) ram ( // Wishbone interface
+ .wb_clk_i(wb_clk),
+ .wb_rst_i(wb_rst),
+
+ .wb_adr_i(wb_m2s_adr),
+ .wb_dat_i(wb_m2s_dat),
+ .wb_stb_i(wb_m2s_stb),
+ .wb_cyc_i(wb_m2s_cyc),
+ .wb_dat_o(wb_s2m_dat),
+ .wb_ack_o(wb_s2m_ack),
+ .wb_sel_i(wb_m2s_sel),
+ .wb_we_i(wb_m2s_we),
+
+ .mem_instr(mem_instr),
+ .tests_passed(tests_passed)
+ );
+
+ picorv32_wb #(
+`ifndef SYNTH_TEST
+`ifdef SP_TEST
+ .ENABLE_REGS_DUALPORT(0),
+`endif
+`ifdef COMPRESSED_ISA
+ .COMPRESSED_ISA(1),
+`endif
+ .ENABLE_MUL(1),
+ .ENABLE_DIV(1),
+ .ENABLE_IRQ(1),
+ .ENABLE_TRACE(1)
+`endif
+ ) uut (
+ .trap (trap),
+ .irq (irq),
+ .trace_valid (trace_valid),
+ .trace_data (trace_data),
+ .mem_instr(mem_instr),
+
+ .wb_clk_i(wb_clk),
+ .wb_rst_i(wb_rst),
+
+ .wbm_adr_o(wb_m2s_adr),
+ .wbm_dat_i(wb_s2m_dat),
+ .wbm_stb_o(wb_m2s_stb),
+ .wbm_ack_i(wb_s2m_ack),
+ .wbm_cyc_o(wb_m2s_cyc),
+ .wbm_dat_o(wb_m2s_dat),
+ .wbm_we_o(wb_m2s_we),
+ .wbm_sel_o(wb_m2s_sel)
+ );
+
+ reg [1023:0] firmware_file;
+ initial begin
+ if (!$value$plusargs("firmware=%s", firmware_file))
+ firmware_file = "firmware/firmware.hex";
+ $readmemh(firmware_file, ram.mem);
+ end
+
+ integer cycle_counter;
+ always @(posedge wb_clk) begin
+ cycle_counter <= !wb_rst ? cycle_counter + 1 : 0;
+ if (!wb_rst && trap) begin
+`ifndef VERILATOR
+ repeat (10) @(posedge wb_clk);
+`endif
+ $display("TRAP after %1d clock cycles", cycle_counter);
+ if (tests_passed) begin
+ $display("ALL TESTS PASSED.");
+ $finish;
+ end else begin
+ $display("ERROR!");
+ if ($test$plusargs("noerror"))
+ $finish;
+ $stop;
+ end
+ end
+ end
+endmodule
+
+/* ISC License
+ *
+ * Verilog on-chip RAM with Wishbone interface
+ *
+ * Copyright (C) 2014, 2016 Olof Kindgren <olof.kindgren@gmail.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.
+ */
+
+module wb_ram #(
+ parameter depth = 256,
+ parameter memfile = "",
+ parameter VERBOSE = 0
+) (
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_adr_i,
+ input [31:0] wb_dat_i,
+ input [3:0] wb_sel_i,
+ input wb_we_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+
+ output reg wb_ack_o,
+ output reg [31:0] wb_dat_o,
+
+ input mem_instr,
+ output reg tests_passed
+);
+
+ reg verbose;
+ initial verbose = $test$plusargs("verbose") || VERBOSE;
+
+ initial tests_passed = 0;
+
+ reg [31:0] adr_r;
+ wire valid = wb_cyc_i & wb_stb_i;
+
+ always @(posedge wb_clk_i) begin
+ adr_r <= wb_adr_i;
+ // Ack generation
+ wb_ack_o <= valid & !wb_ack_o;
+ if (wb_rst_i)
+ begin
+ adr_r <= {32{1'b0}};
+ wb_ack_o <= 1'b0;
+ end
+ end
+
+ wire ram_we = wb_we_i & valid & wb_ack_o;
+
+ wire [31:0] waddr = adr_r[31:2];
+ wire [31:0] raddr = wb_adr_i[31:2];
+ wire [3:0] we = {4{ram_we}} & wb_sel_i;
+
+ wire [$clog2(depth/4)-1:0] raddr2 = raddr[$clog2(depth/4)-1:0];
+ wire [$clog2(depth/4)-1:0] waddr2 = waddr[$clog2(depth/4)-1:0];
+
+ reg [31:0] mem [0:depth/4-1] /* verilator public */;
+
+ always @(posedge wb_clk_i) begin
+ if (ram_we) begin
+ if (verbose)
+ $display("WR: ADDR=%08x DATA=%08x STRB=%04b",
+ adr_r, wb_dat_i, we);
+
+ if (adr_r[31:0] == 32'h1000_0000)
+ if (verbose) begin
+ if (32 <= wb_dat_i[7:0] && wb_dat_i[7:0] < 128)
+ $display("OUT: '%c'", wb_dat_i[7:0]);
+ else
+ $display("OUT: %3d", wb_dat_i[7:0]);
+ end else begin
+ $write("%c", wb_dat_i[7:0]);
+`ifndef VERILATOR
+ $fflush();
+`endif
+ end
+ else
+ if (adr_r[31:0] == 32'h2000_0000)
+ if (wb_dat_i[31:0] == 123456789)
+ tests_passed = 1;
+ end
+ end
+
+ always @(posedge wb_clk_i) begin
+ if (waddr2 < 128 * 1024 / 4) begin
+ if (we[0])
+ mem[waddr2][7:0] <= wb_dat_i[7:0];
+
+ if (we[1])
+ mem[waddr2][15:8] <= wb_dat_i[15:8];
+
+ if (we[2])
+ mem[waddr2][23:16] <= wb_dat_i[23:16];
+
+ if (we[3])
+ mem[waddr2][31:24] <= wb_dat_i[31:24];
+
+ end
+
+ if (valid & wb_ack_o & !ram_we)
+ if (verbose)
+ $display("RD: ADDR=%08x DATA=%08x%s", adr_r, mem[raddr2], mem_instr ? " INSN" : "");
+
+ wb_dat_o <= mem[raddr2];
+ end
+
+ initial begin
+ if (memfile != "")
+ $readmemh(memfile, mem);
+ end
+endmodule