this bram core has taken my soul

This commit is contained in:
Fischer Moseley 2023-04-12 18:15:50 -04:00
parent 36f9791f4d
commit 5ceefc8da9
4 changed files with 45 additions and 81 deletions

View File

@ -673,8 +673,6 @@ class BlockMemoryCore:
from math import ceil, floor, log2
self.addr_width = ceil(log2(self.depth))
self.n_brams = ceil(self.width / 16)
self.n_full_width_brams = floor(self.width / 16)
self.partial_bram_width = self.width - (16 * self.n_full_width_brams)
self.max_addr = self.base_addr + (self.depth * self.n_brams)
def hdl_inst(self):
@ -687,12 +685,6 @@ class BlockMemoryCore:
def hdl_def(self):
bram_core = VerilogManipulator("block_memory_tmpl.v")
bram_core.sub(self.name, "/* NAME */")
bram_core.sub(self.width, "/* WIDTH */")
bram_core.sub(self.depth, "/* DEPTH */")
bram_core.sub(self.max_addr, "/* MAX_ADDR */")
bram_core.sub(self.n_brams, "/* N_BRAMS */")
bram_core.sub(self.n_full_width_brams, "/* N_FULL_WIDTH_BRAMS */")
bram_core.sub(self.partial_bram_width, "/* PARTIAL_BRAM_WIDTH */")
return bram_core.get_hdl()

View File

@ -26,25 +26,28 @@ module /* NAME */ (
input wire user_we);
parameter BASE_ADDR = 0;
localparam BRAM_WIDTH = /* WIDTH */;
localparam BRAM_DEPTH = /* DEPTH */;
parameter BRAM_WIDTH = 0;
parameter BRAM_DEPTH = 0;
localparam ADDR_WIDTH = $clog2(BRAM_DEPTH);
localparam MAX_ADDR = /* MAX_ADDR */;
localparam N_BRAMS = /* N_BRAMS */;
localparam N_FULL_WIDTH_BRAMS = /* N_FULL_WIDTH_BRAMS */;
localparam PARTIAL_BRAM_WIDTH = /* PARTIAL_BRAM_WIDTH */;
localparam N_BRAMS = int'($ceil(real'(BRAM_WIDTH) / 16.0));
localparam MAX_ADDR = BASE_ADDR + (BRAM_DEPTH * N_BRAMS);
// Bus-Controlled side of BRAMs
// Port A of BRAMs
reg [N_BRAMS-1:0][ADDR_WIDTH-1:0] addra = 0;
reg [N_BRAMS-1:0][15:0] dina = 0;
reg [N_BRAMS-1:0][15:0] douta;
reg [N_BRAMS-1:0] wea = 0;
// User-Controlled Side of BRAMs
reg [N_BRAMS-1:0][15:0] dinb = 0;
// Port B of BRAMs
reg [N_BRAMS-1:0][15:0] dinb;
reg [N_BRAMS-1:0][15:0] doutb;
assign dout = {doutb[1], doutb[0]};
assign dinb = user_din;
// kind of a hack to part select from a 2d array that's been flattened to 1d
reg [(N_BRAMS*16)-1:0] doutb_flattened;
assign doutb_flattened = doutb;
assign user_dout = doutb_flattened[BRAM_WIDTH-1:0];
// Pipelining
reg [3:0][15:0] addr_pipe = 0;
@ -88,10 +91,10 @@ module /* NAME */ (
end
end
// generate the full-width BRAMs
// generate the BRAMs
genvar i;
generate
for(i=0; i<N_FULL_WIDTH_BRAMS; i=i+1) begin
for(i=0; i<N_BRAMS; i=i+1) begin
dual_port_bram #(
.RAM_WIDTH(16),
.RAM_DEPTH(BRAM_DEPTH)
@ -111,27 +114,6 @@ module /* NAME */ (
.doutb(doutb[i]),
.web(user_we));
end
if(PARTIAL_BRAM_WIDTH > 0) begin
dual_port_bram #(
.RAM_WIDTH(PARTIAL_BRAM_WIDTH),
.RAM_DEPTH(BRAM_DEPTH)
) bram_partial_width (
// port A is controlled by the bus
.clka(clk),
.addra(addra[N_BRAMS-1]),
.dina(dina[N_BRAMS-1][PARTIAL_BRAM_WIDTH-1:0]),
.douta(douta[N_BRAMS-1]),
.wea(wea[N_BRAMS-1]),
// port B is exposed to the user
.clkb(user_clk),
.addrb(user_addr),
.dinb(dinb[N_BRAMS-1][PARTIAL_BRAM_WIDTH-1:0]),
.doutb(doutb[N_BRAMS-1]),
.web(user_we));
end
endgenerate
endmodule
`default_nettype wire

View File

@ -23,25 +23,28 @@ module my_bram (
input wire user_we);
parameter BASE_ADDR = 0;
localparam BRAM_WIDTH = 18;
localparam BRAM_DEPTH = 256;
parameter BRAM_WIDTH = 0;
parameter BRAM_DEPTH = 0;
localparam ADDR_WIDTH = $clog2(BRAM_DEPTH);
localparam MAX_ADDR = 512;
localparam N_BRAMS = 2;
localparam N_FULL_WIDTH_BRAMS = 1;
localparam PARTIAL_BRAM_WIDTH = 2;
localparam MAX_ADDR = BASE_ADDR + (BRAM_DEPTH * N_BRAMS);
localparam N_BRAMS = int'($ceil(real'(BRAM_WIDTH) / 16.0));
// Bus-Controlled side of BRAMs
// Port A of BRAMs
reg [N_BRAMS-1:0][ADDR_WIDTH-1:0] addra = 0;
reg [N_BRAMS-1:0][15:0] dina = 0;
reg [N_BRAMS-1:0][15:0] douta;
reg [N_BRAMS-1:0] wea = 0;
// User-Controlled Side of BRAMs
reg [N_BRAMS-1:0][15:0] dinb = 0;
// Port B of BRAMs
reg [N_BRAMS-1:0][15:0] dinb;
reg [N_BRAMS-1:0][15:0] doutb;
assign dout = {doutb[1], doutb[0]};
assign dinb = user_din;
// kind of a hack to part select from a 2d array that's been flattened to 1d
reg [(N_BRAMS*16)-1:0] doutb_flattened;
assign doutb_flattened = doutb;
assign user_dout = doutb_flattened[BRAM_WIDTH-1:0];
// Pipelining
reg [3:0][15:0] addr_pipe = 0;
@ -85,10 +88,10 @@ module my_bram (
end
end
// generate the full-width BRAMs
// generate the BRAMs
genvar i;
generate
for(i=0; i<N_FULL_WIDTH_BRAMS; i=i+1) begin
for(i=0; i<N_BRAMS; i=i+1) begin
dual_port_bram #(
.RAM_WIDTH(16),
.RAM_DEPTH(BRAM_DEPTH)
@ -108,26 +111,5 @@ module my_bram (
.doutb(doutb[i]),
.web(user_we));
end
if(PARTIAL_BRAM_WIDTH > 0) begin
dual_port_bram #(
.RAM_WIDTH(PARTIAL_BRAM_WIDTH),
.RAM_DEPTH(BRAM_DEPTH)
) bram_partial_width (
// port A is controlled by the bus
.clka(clk),
.addra(addra[N_BRAMS-1]),
.dina(dina[N_BRAMS-1][PARTIAL_BRAM_WIDTH-1:0]),
.douta(douta[N_BRAMS-1]),
.wea(wea[N_BRAMS-1]),
// port B is exposed to the user
.clkb(user_clk),
.addrb(user_addr),
.dinb(dinb[N_BRAMS-1][PARTIAL_BRAM_WIDTH-1:0]),
.doutb(doutb[N_BRAMS-1]),
.web(user_we));
end
endgenerate
endmodule

View File

@ -74,12 +74,15 @@ module block_memory_tb;
logic bc_tb_valid;
// bram itself
logic [7:0] bram_user_addr = 0;
logic [17:0] bram_user_din = 0;
logic [17:0] bram_user_dout;
localparam BRAM_DEPTH = 256;
localparam BRAM_WIDTH = 33;
localparam ADDR_WIDTH = $clog2(BRAM_WIDTH);
logic [ADDR_WIDTH-1:0] bram_user_addr = 0;
logic [BRAM_WIDTH-1:0] bram_user_din = 0;
logic [BRAM_WIDTH-1:0] bram_user_dout;
logic bram_user_we = 0;
my_bram my_bram_inst(
my_bram #(.BRAM_DEPTH(BRAM_DEPTH), .BRAM_WIDTH(BRAM_WIDTH)) my_bram_inst(
.clk(clk),
.addr_i(tb_bc_addr),
@ -109,6 +112,8 @@ module block_memory_tb;
$dumpfile("block_memory_tb.vcd");
$dumpvars(0, block_memory_tb);
$display("i am going to vomit %d", my_bram_inst.N_BRAMS);
// setup and reset
clk = 0;
test_num = 0;
@ -132,11 +137,14 @@ module block_memory_tb;
/* ==== Test 1 Begin ==== */
$display("\n=== test 1: read/write from BRAM, verify ===");
test_num = 1;
//read_reg(0, read_value, "lmao");
write_and_verify(0, 4, "larry_op");
write_and_verify(1, 3, "larry_op");
write_and_verify(3, 'h1234, "");
write_and_verify(4, 'h5678, "");
write_and_verify(5, 'h0001, "");
// now query what's on the the user side at address 0
bram_user_addr = 1;
#(3*`CP);
$display("Found 0x%h on the other side", bram_user_dout);
#(10*`CP);