verilator/test_regress/t/t_order_multidriven.v

183 lines
3.4 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2013 Ted Campbell
// SPDX-License-Identifier: CC0-1.0
//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 reg [7:0] a_rdata,
input b_clk,
input b_wen,
input [7:0] b_addr,
input [7:0] b_wdata,
output reg [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