upsilon/gateware/rtl/bram/bram.v

66 lines
1.7 KiB
Coq
Raw Normal View History

2024-01-20 15:23:40 -05:00
/* 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.
*
* This BRAM can only handle aligned accesses.
2024-01-20 15:23:40 -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,
input [BUS_WID-1:0] wb_dat_w,
2024-01-20 15:23:40 -05:00
output reg wb_ack,
2024-02-08 07:57:22 -05:00
output reg [BUS_WID-1:0] wb_dat_r
2024-01-20 15:23:40 -05:00
);
2024-02-08 07:57:22 -05:00
initial wb_ack <= 0;
initial wb_dat_r <= 0;
/* 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.
*/
2024-02-08 07:57:22 -05:00
(* ram_style = "block" *)
reg [WORD_WID-1:0] buffer [(ADDR_MASK >> 2):0];
2024-01-20 15:23:40 -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
2024-02-08 07:57:22 -05:00
always @ (posedge clk) if (wb_cyc && wb_stb && !wb_ack) begin
wb_ack <= 1;
if (wb_we) begin
if (wb_sel[0])
buffer[ind][7:0] <= wb_dat_w[7:0];
if (wb_sel[1])
buffer[ind][15:8] <= wb_dat_w[15:8];
if (wb_sel[2])
buffer[ind][23:16] <= wb_dat_w[23:16];
if (wb_sel[3])
buffer[ind][31:24] <= wb_dat_w[31:24];
2024-01-20 15:23:40 -05:00
end else begin
2024-02-08 07:57:22 -05:00
wb_dat_r <= buffer[ind];
2024-01-20 15:23:40 -05:00
end
2024-02-08 07:57:22 -05:00
end else if (!wb_stb) begin
2024-01-20 15:23:40 -05:00
wb_ack <= 0;
end
endmodule