diff options
Diffstat (limited to 'picorv32/testbench_wb.v')
-rw-r--r-- | picorv32/testbench_wb.v | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/picorv32/testbench_wb.v b/picorv32/testbench_wb.v new file mode 100644 index 0000000..4e1a8eb --- /dev/null +++ b/picorv32/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 |