`timescale 1 ns / 1 ns module regfile_tb(); parameter Td2 = 5; // the half of the period parameter Nd = 16; // the data size parameter Na = 3; // the address size parameter Nreg = (1 << Na); // the number of registers reg clk, rst_n, we; wire [Nd-1:0] rda, rdb; // read data reg [Nd-1:0] d; // write data reg [Na-1:0] wa, ra, rb; // addresses reg [Nd-1:0] regm [0:Nreg-1]; // shadow memory for the regs integer i; // loop index regfile dut(.clk(clk), .rst_n(rst_n), .we(we), .din(d), .waddr(wa), .raddra(ra), .raddrb(rb), .rdata(rda), .rdatb(rdb)); defparam dut.Nd = Nd; // map the parameters defparam dut.Na = Na; always # Td2 clk = ~clk; // generate the clock initial begin $dumpfile("regfile.vcd"); $dumpvars(1, regfile_tb.dut); end initial $monitor("Zeit: %t, write enable changed to: %b", $time, we); initial begin clk = 1'b0; // initial value of the clock rst_n = 0; // power up reset repeat (2) @(negedge clk); rst_n = 1; // deactivate the reset for (i = 0; i < Nreg; i = i + 1) // write some pattern write_reg(i, i | (i+1) << 8); for (i = 0; i < Nreg; i = i + 1) // read back read_reg(0, i, regm[i]); // using port A for (i = 0; i < Nreg; i = i + 1) read_reg(1, i, regm[i]); // and port B rst_n = 0; // reset @(negedge clk); rst_n = 1; for (i = 0; i < Nreg; i = i + 1) // read and expect 0 read_reg(0, i, 0); for (i = 0; i < Nreg; i = i + 1) // from both ports read_reg(1, i, 0); end task write_reg; input [Na-1:0] rega; input [Nd-1:0] regd; begin we = 1; d = regd; wa = rega; @ (negedge clk); regm[rega] = regd; we = 0; end endtask task read_reg; input prt; // 0 or 1 input [Na-1:0] rega; input [Nd-1:0] regd; begin we = 0; if (prt==0) ra = rega; else rb = rega; @ (negedge clk); if ((prt==0) && (rda != regd)) $display("%t : expected 0x%04x, readA 0x%04x, reg# %d", $time, regd, rda, rega); if ((prt==1) && (rdb != regd)) $display("%t : expected 0x%04x, readB 0x%04x, reg# %d", $time, regd, rdb, rega); end endtask endmodule