blob: 250dc8ea3d6ef0582a8fbe73c4336d791f228937 [file] [log] [blame]
// Inferred RAM to work around limitations in Openlane.
//
// Wishbone interface based on mem_wb.v from Caravel.
`default_nettype none
module mem_ff_wb #(
parameter MEM_WORDS = 256
)(
input wb_clk_i,
input wb_rst_i,
input [31:0] wb_adr_i,
input [31:0] wb_dat_i,
input [3:0] wb_sel_i,
input wb_we_i,
input wb_cyc_i,
input wb_stb_i,
output wb_ack_o,
output [31:0] wb_dat_o
);
localparam ADR_WIDTH = $clog2(MEM_WORDS);
wire valid;
wire ram_wen;
wire [3:0] wen; // write enable
assign valid = wb_cyc_i & wb_stb_i;
assign ram_wen = wb_we_i && valid;
assign wen = wb_sel_i & {4{ram_wen}} ;
/*
Ack Generation
- write transaction: asserted upon receiving adr_i & dat_i
- read transaction : asserted one clock cycle after receiving the adr_i & dat_i
*/
reg wb_ack_read;
reg wb_ack_o;
always @(posedge wb_clk_i) begin
if (wb_rst_i == 1'b 1) begin
wb_ack_read <= 1'b0;
wb_ack_o <= 1'b0;
end else begin
// wb_ack_read <= {2{valid}} & {1'b1, wb_ack_read[1]};
wb_ack_o <= wb_we_i? (valid & !wb_ack_o): wb_ack_read;
wb_ack_read <= (valid & !wb_ack_o) & !wb_ack_read;
end
end
ff32_ram #(
.ADDR_WIDTH(ADR_WIDTH)
) ram (
.clk(wb_clk_i),
.addr(wb_adr_i[ADR_WIDTH+1:2]),
.din(wb_dat_i),
.dout(wb_dat_o),
.en(valid),
.wmask(wen)
);
endmodule
`default_nettype wire
// Single port 32-bit inferred RAM.
module ff32_ram #(
parameter ADDR_WIDTH = 8
)(
input clk,
input [ADDR_WIDTH-1:0] addr,
input [31:0] din,
output reg [31:0] dout,
input en,
input [3:0] wmask
);
reg [7:0] ram0 [(1<<ADDR_WIDTH)-1:0];
reg [7:0] ram1 [(1<<ADDR_WIDTH)-1:0];
reg [7:0] ram2 [(1<<ADDR_WIDTH)-1:0];
reg [7:0] ram3 [(1<<ADDR_WIDTH)-1:0];
`ifdef SIM
integer i;
initial begin
for (i = 0; i < (1<<ADDR_WIDTH); i = i + 1) begin
ram0[i] = 8'b0;
ram1[i] = 8'b0;
ram2[i] = 8'b0;
ram3[i] = 8'b0;
end
end
`endif
// Write.
always @(posedge clk) begin
if (en) begin
if (wmask[0])
ram0[addr] <= din[7:0];
if (wmask[1])
ram1[addr] <= din[15:8];
if (wmask[2])
ram2[addr] <= din[23:16];
if (wmask[3])
ram3[addr] <= din[31:24];
end
end
// Read.
always @(posedge clk) begin
if (en) begin
dout[7:0] <= ram0[addr];
dout[15:8] <= ram1[addr];
dout[23:16] <= ram2[addr];
dout[31:24] <= ram3[addr];
end
end
endmodule // module ff32_ram