Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Single port memories #1607

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 13 additions & 21 deletions primitives/memories.futil
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,27 @@ extern "memories.sv" {
@clk clk: 1,
@reset reset: 1,
@data addr0: IDX_SIZE,
@static(1) @go(1) content_en: 1
// Write ports
@write_together(1) @static(1) @go(1) write_en: 1,
@write_together(1) write_en: 1,
@write_together(1) @data write_data: WIDTH,
// Read ports
@static(1) @go(2) read_en: 1
) -> (
@stable read_data: WIDTH,
@done(1) write_done: 1,
@done(2) read_done: 1
@done(1) done: 1
);

primitive seq_mem_d2[WIDTH, D0_SIZE, D1_SIZE, D0_IDX_SIZE, D1_IDX_SIZE](
@clk clk: 1,
@reset reset: 1,
@data addr0: D0_IDX_SIZE,
@data addr1: D1_IDX_SIZE,
@static(1) @go(1) content_en: 1
// Write ports
@write_together(1) @static(1) @go(1) write_en: 1,
@write_together(1) write_en: 1,
@write_together(1) @data write_data: WIDTH,
// Read ports
@static(1) @go(2) read_en: 1
) -> (
@stable read_data: WIDTH,
@done(1) write_done: 1,
@done(2) read_done: 1
@done(1) done: 1,
);

primitive seq_mem_d3[WIDTH, D0_SIZE, D1_SIZE, D2_SIZE, D0_IDX_SIZE, D1_IDX_SIZE, D2_IDX_SIZE](
Expand All @@ -36,15 +32,13 @@ extern "memories.sv" {
@data addr0: D0_IDX_SIZE,
@data addr1: D1_IDX_SIZE,
@data addr2: D2_IDX_SIZE,
@static(1) @go(1) content_en: 1
// Write ports
@write_together(1) @static(1) @go(1) write_en: 1,
@write_together(1) write_en: 1,
@write_together(1) @data write_data: WIDTH,
// Read ports
@static(1) @go(2) read_en: 1
) -> (
@stable read_data: WIDTH,
@done(1) write_done: 1,
@done(2) read_done: 1
@done(1) done: 1,
);

primitive seq_mem_d4[WIDTH, D0_SIZE, D1_SIZE, D2_SIZE, D3_SIZE, D0_IDX_SIZE, D1_IDX_SIZE, D2_IDX_SIZE, D3_IDX_SIZE](
Expand All @@ -54,14 +48,12 @@ extern "memories.sv" {
@data addr1: D1_IDX_SIZE,
@data addr2: D2_IDX_SIZE,
@data addr3: D3_IDX_SIZE,
@static(1) @go(1) content_en: 1
// Write ports
@write_together(1) @static(1) @go(1) write_en: 1,
@write_together(1) write_en: 1,
@write_together(1) @data write_data: WIDTH,
// Read ports
@static(1) @go(2) read_en: 1
) -> (
@stable read_data: WIDTH,
@done(1) write_done: 1,
@done(2) read_done: 1
@done(1) done: 1,
);
}
}
77 changes: 29 additions & 48 deletions primitives/memories.sv
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,18 @@ module seq_mem_d1 #(
input wire logic clk,
input wire logic reset,
input wire logic [IDX_SIZE-1:0] addr0,
input wire logic content_en,
output logic done,

// Read signal
input wire logic read_en,
output logic [ WIDTH-1:0] read_data,
output logic read_done,

// Write signals
input wire logic [ WIDTH-1:0] write_data,
input wire logic write_en,
output logic write_done
input wire logic write_en
);
// Internal memory
(* ram_style = "ultra" *) logic [WIDTH-1:0] mem[SIZE-1:0];
logic [WIDTH-1:0] mem[SIZE-1:0];

// Register for the read output
logic [WIDTH-1:0] read_out;
Expand All @@ -36,60 +35,45 @@ module seq_mem_d1 #(
always_ff @(posedge clk) begin
if (reset) begin
read_out <= '0;
end else if (read_en) begin
end else if (content_en && !write_en) begin
/* verilator lint_off WIDTH */
read_out <= mem[addr0];
end else if (write_en) begin
end else if (content_en && write_en) begin
// Explicitly clobber the read output when a write is performed
read_out <= 'x;
end else begin
read_out <= read_out;
end
end

// Propagate the read_done signal
// Propagate the done signal
always_ff @(posedge clk) begin
if (reset) begin
read_done <= '0;
end else if (read_en) begin
read_done <= '1;
done <= '0;
end else if (content_en) begin
done <= '1;
end else begin
read_done <= '0;
done <= '0;
end
end

// Write value to the memory
always_ff @(posedge clk) begin
if (!reset && write_en)
if (!reset && content_en && write_en)
mem[addr0] <= write_data;
end

// Propagate the write_done signal
always_ff @(posedge clk) begin
if (reset) begin
write_done <= '0;
end else if (write_en) begin
write_done <= 1'd1;
end else begin
write_done <= '0;
end
end

// Check for out of bounds access
`ifdef VERILATOR
always_comb begin
if (read_en)
if (content_en && !write_en)
if (addr0 >= SIZE)
$error(
"std_mem_d1: Out of bounds access\n",
"addr0: %0d\n", addr0,
"SIZE: %0d", SIZE
);
end
always_comb begin
if (read_en && write_en)
$error("Simultaneous read and write attempted\n");
end
`endif
endmodule

Expand All @@ -105,24 +89,23 @@ module seq_mem_d2 #(
input wire logic reset,
input wire logic [D0_IDX_SIZE-1:0] addr0,
input wire logic [D1_IDX_SIZE-1:0] addr1,
input wire logic content_en,
output logic done,

// Read signal
input wire logic read_en,
output logic [WIDTH-1:0] read_data,
output logic read_done,

// Write signals
input wire logic write_en,
input wire logic [ WIDTH-1:0] write_data,
output logic write_done
input wire logic [ WIDTH-1:0] write_data
);
wire [D0_IDX_SIZE+D1_IDX_SIZE-1:0] addr;
assign addr = addr0 * D1_SIZE + addr1;

seq_mem_d1 #(.WIDTH(WIDTH), .SIZE(D0_SIZE * D1_SIZE), .IDX_SIZE(D0_IDX_SIZE+D1_IDX_SIZE)) mem
(.clk(clk), .reset(reset), .addr0(addr),
.read_en(read_en), .read_data(read_data), .read_done(read_done), .write_data(write_data), .write_en(write_en),
.write_done(write_done));
.content_en(content_en), .read_data(read_data), .write_data(write_data), .write_en(write_en),
.done(done));
endmodule

module seq_mem_d3 #(
Expand All @@ -140,24 +123,23 @@ module seq_mem_d3 #(
input wire logic [D0_IDX_SIZE-1:0] addr0,
input wire logic [D1_IDX_SIZE-1:0] addr1,
input wire logic [D2_IDX_SIZE-1:0] addr2,
input wire logic content_en,
output logic done,

// Read signal
input wire logic read_en,
output logic [WIDTH-1:0] read_data,
output logic read_done,

// Write signals
input wire logic write_en,
input wire logic [ WIDTH-1:0] write_data,
output logic write_done
input wire logic [ WIDTH-1:0] write_data
);
wire [D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE-1:0] addr;
assign addr = addr0 * (D1_SIZE * D2_SIZE) + addr1 * (D2_SIZE) + addr2;

seq_mem_d1 #(.WIDTH(WIDTH), .SIZE(D0_SIZE * D1_SIZE * D2_SIZE), .IDX_SIZE(D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE)) mem
(.clk(clk), .reset(reset), .addr0(addr),
.read_en(read_en), .read_data(read_data), .read_done(read_done), .write_data(write_data), .write_en(write_en),
.write_done(write_done));
.content_en(content_en), .read_data(read_data), .write_data(write_data), .write_en(write_en),
.done(done));
endmodule

module seq_mem_d4 #(
Expand All @@ -178,22 +160,21 @@ module seq_mem_d4 #(
input wire logic [D1_IDX_SIZE-1:0] addr1,
input wire logic [D2_IDX_SIZE-1:0] addr2,
input wire logic [D3_IDX_SIZE-1:0] addr3,
input wire logic content_en,
output logic done,

// Read signal
input wire logic read_en,
output logic [WIDTH-1:0] read_data,
output logic read_done,

// Write signals
input wire logic write_en,
input wire logic [ WIDTH-1:0] write_data,
output logic write_done
input wire logic [ WIDTH-1:0] write_data
);
wire [D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE+D3_IDX_SIZE-1:0] addr;
assign addr = addr0 * (D1_SIZE * D2_SIZE * D3_SIZE) + addr1 * (D2_SIZE * D3_SIZE) + addr2 * (D3_SIZE) + addr3;

seq_mem_d1 #(.WIDTH(WIDTH), .SIZE(D0_SIZE * D1_SIZE * D2_SIZE * D3_SIZE), .IDX_SIZE(D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE+D3_IDX_SIZE)) mem
(.clk(clk), .reset(reset), .addr0(addr),
.read_en(read_en), .read_data(read_data), .read_done(read_done), .write_data(write_data), .write_en(write_en),
.write_done(write_done));
endmodule
.content_en(content_en), .read_data(read_data), .write_data(write_data), .write_en(write_en),
.done(done));
endmodule
11 changes: 7 additions & 4 deletions tests/correctness/seq-mem-d4-add.futil
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ component main() -> () {
in1.addr1 = j.out;
in1.addr2 = k.out;
in1.addr3 = l.out;
in1.read_en = 1'd1;
in1_reg.write_en = in1.read_done;
in1.content_en = 1'd1;
in1.write_en = 1'd0;
in1_reg.write_en = in1.done;
in1_reg.in = in1.read_data;
read_in1[done] = in1_reg.done;
}
Expand All @@ -84,8 +85,9 @@ component main() -> () {
in2.addr1 = j.out;
in2.addr2 = k.out;
in2.addr3 = l.out;
in2.read_en = 1'd1;
in2_reg.write_en = in2.read_done;
in2.content_en = 1'd1;
in2.write_en = 1'd0;
in2_reg.write_en = in2.done;
in2_reg.in = in2.read_data;
read_in2[done] = in2_reg.done;
}
Expand All @@ -96,6 +98,7 @@ component main() -> () {
out.addr1 = j.out;
out.addr2 = k.out;
out.addr3 = l.out;
out.content_en = 1'd1;
out.write_en = 1'd1;
out.write_data = add.out;
update_val[done] = out.write_done;
Expand Down
13 changes: 9 additions & 4 deletions tests/correctness/seq-mem-dot-product.futil
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,38 @@ component main() -> () {

// Prime memories for reading
group prime_in1 {
in1.read_en = 1'd1;
in1.content_en = 1'd1;
in1.write_en = 1'd0;
in1.addr0 = idx.out;
prime_in1[done] = in1.read_done;
prime_in1[done] = in1.done;
}
group prime_in2 {
in2.read_en = 1'd1;
in2.content_en = 1'd1;
in2.write_en = 1'd0;
in2.addr0 = idx.out;
prime_in2[done] = in2.read_done;
prime_in2[done] = in2.done;
}

// Computation
group init_tmp {
tmp.in = 32'd0;
tmp.content_en = 1'd1;
tmp.write_en = 1'd1;
init_tmp[done] = tmp.done;
}
group do_add {
add.left = tmp.out;
add.right = mult.out;
tmp.in = add.out;
tmp.content_en = 1'd1;
tmp.write_en = 1'd1;
do_add[done] = tmp.done;
}

// Write to output
group write {
out.addr0 = 1'd0;
out.content_en = 1'd1;
out.write_en = 1'd1;
out.write_data = tmp.out;
write[done] = out.write_done;
Expand Down