2024-01-20 15:23:40 -05:00
|
|
|
m4_changequote(`⟨', `⟩')
|
|
|
|
m4_changecom(⟨/*⟩, ⟨*/⟩)
|
|
|
|
|
|
|
|
/* Copyright 2024 (C) Peter McGoron
|
|
|
|
* This file is a part of Upsilon, a free and open source software project.
|
|
|
|
* For license terms, refer to the files in `doc/copying` in the Upsilon
|
|
|
|
* source distribution.
|
|
|
|
*
|
2024-01-20 23:38:34 -05:00
|
|
|
* This BRAM can only handle aligned accesses.
|
2024-01-20 15:23:40 -05:00
|
|
|
*/
|
2024-01-20 23:38:34 -05:00
|
|
|
module bram #(
|
2024-01-20 15:23:40 -05:00
|
|
|
/* Width of the memory bus */
|
|
|
|
parameter BUS_WID = 32,
|
|
|
|
/* Width of a request. */
|
|
|
|
parameter WORD_WID = 32,
|
|
|
|
/* Bitmask used to extract the RAM location in the buffer. */
|
|
|
|
parameter ADDR_MASK = 32'h1FFF
|
|
|
|
) (
|
|
|
|
input clk,
|
|
|
|
|
|
|
|
input wb_cyc,
|
|
|
|
input wb_stb,
|
|
|
|
input wb_we,
|
|
|
|
input [4-1:0] wb_sel,
|
|
|
|
input [BUS_WID-1:0] wb_addr,
|
2024-01-20 23:38:34 -05:00
|
|
|
input [BUS_WID-1:0] wb_dat_w,
|
2024-01-20 15:23:40 -05:00
|
|
|
output reg wb_ack,
|
2024-01-20 23:38:34 -05:00
|
|
|
output reg [BUS_WID-1:0] wb_dat_r,
|
2024-01-20 15:23:40 -05:00
|
|
|
);
|
|
|
|
|
2024-01-20 23:38:34 -05:00
|
|
|
/* When the size of the memory is a power of 2, the mask is the
|
|
|
|
* last addressable index in the array.
|
|
|
|
*
|
|
|
|
* Since this buffer stores words, this is divided by 4 (32 bits).
|
|
|
|
* When accessing a single byte, the address
|
|
|
|
* 0b......Xab
|
|
|
|
* is shifted to the right by two bits, throwing away "ab". This indexes
|
|
|
|
* the 32 bit word that contains the address. This applies to halfwords
|
|
|
|
* and words as long as the accesses are aligned.
|
|
|
|
*/
|
|
|
|
reg [WORD_WID-1:0] buffer [(ADDR_MASK >> 2):0];
|
2024-01-20 15:23:40 -05:00
|
|
|
|
2024-01-20 23:38:34 -05:00
|
|
|
/* Current index into the buffer. */
|
|
|
|
wire [13-1:0] ind = (wb_addr & ADDR_MASK) >> 2;
|
2024-01-20 15:23:40 -05:00
|
|
|
|
|
|
|
m4_define(⟨bufwrite⟩, ⟨begin
|
2024-01-20 23:38:34 -05:00
|
|
|
buffer[ind] <= (buffer[ind] & $1) | wb_dat_w[$2];
|
2024-01-20 15:23:40 -05:00
|
|
|
end⟩)
|
|
|
|
|
|
|
|
always @ (posedge clk) if (wb_cyc && wb_stb && !wb_ack)
|
|
|
|
if (!wb_we) begin
|
2024-01-20 23:38:34 -05:00
|
|
|
wb_dat_r <= buffer[ind];
|
2024-01-20 15:23:40 -05:00
|
|
|
wb_ack <= 1;
|
|
|
|
end else begin
|
|
|
|
wb_ack <= 1;
|
|
|
|
case (wb_sel)
|
2024-01-20 23:38:34 -05:00
|
|
|
4'b1111: buffer[ind] <= wb_dat_w;
|
|
|
|
4'b0011: bufwrite(32'hFFFF0000, 15:0)
|
|
|
|
4'b1100: bufwrite(32'h0000FFFF, 31:16)
|
2024-01-20 15:23:40 -05:00
|
|
|
4'b0001: bufwrite(32'hFFFFFF00, 7:0)
|
|
|
|
4'b0010: bufwrite(32'hFFFF00FF, 15:8)
|
|
|
|
4'b0100: bufwrite(32'hFF00FFFF, 23:16)
|
|
|
|
4'b1000: bufwrite(32'h00FFFFFF, 31:24)
|
2024-01-20 23:38:34 -05:00
|
|
|
default: ;
|
2024-01-20 15:23:40 -05:00
|
|
|
endcase
|
|
|
|
end
|
|
|
|
else if (!wb_stb) begin
|
|
|
|
wb_ack <= 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule
|