mirror of
https://github.com/verilator/verilator.git
synced 2025-01-07 15:17:36 +00:00
193 lines
4.5 KiB
Verilog
193 lines
4.5 KiB
Verilog
// 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
|