| // DESCRIPTION: Verilator: Verilog Test module |
| // |
| // This file ONLY is placed into the Public Domain, for any use, |
| // without warranty, 2013 by Ted Campbell. |
| |
| //With MULTI_CLK defined shows bug, without it is hidden |
| `define MULTI_CLK |
| |
| //bug634 |
| |
| module t ( |
| input i_clk_wr, |
| input i_clk_rd |
| ); |
| |
| wire wr$wen; |
| wire [7:0] wr$addr; |
| wire [7:0] wr$wdata; |
| wire [7:0] wr$rdata; |
| |
| wire rd$wen; |
| wire [7:0] rd$addr; |
| wire [7:0] rd$wdata; |
| wire [7:0] rd$rdata; |
| |
| wire clk_wr; |
| wire clk_rd; |
| |
| `ifdef MULTI_CLK |
| assign clk_wr = i_clk_wr; |
| assign clk_rd = i_clk_rd; |
| `else |
| assign clk_wr = i_clk_wr; |
| assign clk_rd = i_clk_wr; |
| `endif |
| |
| FooWr u_wr ( |
| .i_clk ( clk_wr ), |
| |
| .o_wen ( wr$wen ), |
| .o_addr ( wr$addr ), |
| .o_wdata ( wr$wdata ), |
| .i_rdata ( wr$rdata ) |
| ); |
| |
| FooRd u_rd ( |
| .i_clk ( clk_rd ), |
| |
| .o_wen ( rd$wen ), |
| .o_addr ( rd$addr ), |
| .o_wdata ( rd$wdata ), |
| .i_rdata ( rd$rdata ) |
| ); |
| |
| FooMem u_mem ( |
| .iv_clk ( {clk_wr, clk_rd } ), |
| .iv_wen ( {wr$wen, rd$wen } ), |
| .iv_addr ( {wr$addr, rd$addr } ), |
| .iv_wdata ( {wr$wdata,rd$wdata} ), |
| .ov_rdata ( {wr$rdata,rd$rdata} ) |
| ); |
| |
| endmodule |
| |
| |
| // Memory Writer |
| module FooWr( |
| input i_clk, |
| |
| output o_wen, |
| output [7:0] o_addr, |
| output [7:0] o_wdata, |
| input [7:0] i_rdata |
| ); |
| |
| reg [7:0] cnt = 0; |
| |
| // Count [0,200] |
| always @( posedge i_clk ) |
| if ( cnt < 8'd50 ) |
| cnt <= cnt + 8'd1; |
| |
| // Write addr in (10,30) if even |
| assign o_wen = ( cnt > 8'd10 ) && ( cnt < 8'd30 ) && ( cnt[0] == 1'b0 ); |
| assign o_addr = cnt; |
| assign o_wdata = cnt; |
| |
| endmodule |
| |
| |
| // Memory Reader |
| module FooRd( |
| input i_clk, |
| |
| output o_wen, |
| output [7:0] o_addr, |
| output [7:0] o_wdata, |
| input [7:0] i_rdata |
| ); |
| |
| reg [7:0] cnt = 0; |
| reg [7:0] addr_r; |
| reg en_r; |
| |
| // Count [0,200] |
| always @( posedge i_clk ) |
| if ( cnt < 8'd200 ) |
| cnt <= cnt + 8'd1; |
| |
| // Read data |
| assign o_wen = 0; |
| assign o_addr = cnt - 8'd100; |
| |
| // Track issued read |
| always @( posedge i_clk ) |
| begin |
| addr_r <= o_addr; |
| en_r <= ( cnt > 8'd110 ) && ( cnt < 8'd130 ) && ( cnt[0] == 1'b0 ); |
| end |
| |
| // Display to console 100 cycles after writer |
| always @( negedge i_clk ) |
| if ( en_r ) begin |
| `ifdef TEST_VERBOSE |
| $display( "MEM[%x] == %x", addr_r, i_rdata ); |
| `endif |
| if (addr_r != i_rdata) $stop; |
| end |
| |
| endmodule |
| |
| |
| // Multi-port memory abstraction |
| module FooMem( |
| input [2 -1:0] iv_clk, |
| input [2 -1:0] iv_wen, |
| input [2*8-1:0] iv_addr, |
| input [2*8-1:0] iv_wdata, |
| output [2*8-1:0] ov_rdata |
| ); |
| |
| FooMemImpl u_impl ( |
| .a_clk ( iv_clk [0*1+:1] ), |
| .a_wen ( iv_wen [0*1+:1] ), |
| .a_addr ( iv_addr [0*8+:8] ), |
| .a_wdata ( iv_wdata[0*8+:8] ), |
| .a_rdata ( ov_rdata[0*8+:8] ), |
| |
| .b_clk ( iv_clk [1*1+:1] ), |
| .b_wen ( iv_wen [1*1+:1] ), |
| .b_addr ( iv_addr [1*8+:8] ), |
| .b_wdata ( iv_wdata[1*8+:8] ), |
| .b_rdata ( ov_rdata[1*8+:8] ) |
| ); |
| |
| endmodule |
| |
| |
| // Dual-Port L1 Memory Implementation |
| module FooMemImpl( |
| input a_clk, |
| input a_wen, |
| input [7:0] a_addr, |
| input [7:0] a_wdata, |
| output [7:0] a_rdata, |
| |
| input b_clk, |
| input b_wen, |
| input [7:0] b_addr, |
| input [7:0] b_wdata, |
| output [7:0] b_rdata |
| ); |
| |
| /* verilator lint_off MULTIDRIVEN */ |
| reg [7:0] mem[0:255]; |
| /* verilator lint_on MULTIDRIVEN */ |
| |
| always @( posedge a_clk ) |
| if ( a_wen ) |
| mem[a_addr] <= a_wdata; |
| |
| always @( posedge b_clk ) |
| if ( b_wen ) |
| mem[b_addr] <= b_wdata; |
| |
| always @( posedge a_clk ) |
| a_rdata <= mem[a_addr]; |
| |
| always @( posedge b_clk ) |
| b_rdata <= mem[b_addr]; |
| |
| endmodule |