183 lines
3.4 KiB
Systemverilog
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
|