96 lines
3.0 KiB
Verilog
96 lines
3.0 KiB
Verilog
/**********************************************************************
|
|
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
|
|
* Version 3, April 2008 *
|
|
* *
|
|
* Copyright (C) 2018 Luke Wren *
|
|
* *
|
|
* Everyone is permitted to copy and distribute verbatim or modified *
|
|
* copies of this license document and accompanying software, and *
|
|
* changing either is allowed. *
|
|
* *
|
|
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
|
|
* *
|
|
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
|
|
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
|
|
* *
|
|
*********************************************************************/
|
|
|
|
// Register file
|
|
// Single write port, dual read port
|
|
|
|
// FAKE_DUALPORT: if 1, implement regfile with pair of memories.
|
|
// Write ports are ganged together, read ports operate independently.
|
|
// This allows BRAM inference on FPGAs with single-read-port BRAMs.
|
|
// (Looking at you iCE40)
|
|
|
|
module hazard3_regfile_1w2r #(
|
|
parameter FAKE_DUALPORT = 0,
|
|
parameter RESET_REGS = 0, // Unsupported for FAKE_DUALPORT
|
|
parameter N_REGS = 16,
|
|
parameter W_DATA = 32,
|
|
parameter W_ADDR = $clog2(W_DATA) // should be localparam. ISIM...
|
|
) (
|
|
input wire clk,
|
|
input wire rst_n,
|
|
|
|
input wire [W_ADDR-1:0] raddr1,
|
|
output reg [W_DATA-1:0] rdata1,
|
|
|
|
input wire [W_ADDR-1:0] raddr2,
|
|
output reg [W_DATA-1:0] rdata2,
|
|
|
|
input wire [W_ADDR-1:0] waddr,
|
|
input wire [W_DATA-1:0] wdata,
|
|
input wire wen
|
|
);
|
|
|
|
generate
|
|
if (FAKE_DUALPORT) begin: fake_dualport
|
|
reg [W_DATA-1:0] mem1 [0:N_REGS-1];
|
|
reg [W_DATA-1:0] mem2 [0:N_REGS-1];
|
|
|
|
always @ (posedge clk) begin
|
|
if (wen) begin
|
|
mem1[waddr] <= wdata;
|
|
mem2[waddr] <= wdata;
|
|
end
|
|
rdata1 <= mem1[raddr1];
|
|
rdata2 <= mem2[raddr2];
|
|
end
|
|
end else if (RESET_REGS) begin: real_dualport_reset
|
|
// This will presumably always be implemented with flops
|
|
reg [W_DATA-1:0] mem [0:N_REGS-1];
|
|
|
|
integer i;
|
|
always @ (posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
// It's best to ask nicely:
|
|
// synthesis please_on
|
|
for (i = 0; i < N_REGS; i = i + 1) begin
|
|
mem[i] <= {W_DATA{1'b0}};
|
|
end
|
|
// synthesis please_off
|
|
end else begin
|
|
if (wen) begin
|
|
mem[waddr] <= wdata;
|
|
end
|
|
rdata1 <= mem[raddr1];
|
|
rdata2 <= mem[raddr2];
|
|
end
|
|
end
|
|
end else begin: real_dualport_noreset
|
|
// This should be inference-compatible on FPGAs with dual-port BRAMs
|
|
reg [W_DATA-1:0] mem [0:N_REGS-1];
|
|
|
|
always @ (posedge clk) begin
|
|
if (wen) begin
|
|
mem[waddr] <= wdata;
|
|
end
|
|
rdata1 <= mem[raddr1];
|
|
rdata2 <= mem[raddr2];
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|