this bram core has taken my soul
This commit is contained in:
parent
36f9791f4d
commit
5ceefc8da9
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue