I'm vaguely following this tutorial with my ice40 breakout board. I've got to step 11 around separating out the memory into a module, and I cannot seem to persuade yosys to synthesise BRAM.
This is my memory module:
module memory (
input CLK,
input [31:0] memory_address, // the address to be read
output reg [31:0] memory_read_data, // the data read from memory
input memory_read_strobe // raised when address is valid to trigger read
);
parameter SIZE = 256 - 1;
reg [31:0] MEM[SIZE:0];
integer i;
initial begin
// f7 rs2 rs1 f3 rd opcode
// add x1, x1, x2
// add x2 x1 add x1 alureg
MEM[0] = 32'b0000000_00010_00001_000_00001_0000001;
// add x1, x1, x2
// add x2 x1 add x1 alureg
MEM[1] = 32'b0000000_00010_00001_000_00001_0000010;
// add x1, x1, x2
// add x2 x1 add x1 alureg
MEM[2] = 32'b0000000_00010_00001_000_00001_0000100;
MEM[3] = 32'b0000000_00010_00001_000_00001_0001000;
MEM[4] = 32'b0000000_00010_00001_000_00001_0010000;
MEM[5] = 32'b0000000_00010_00001_000_00001_0100000;
MEM[6] = 32'b0000000_00010_00001_000_00001_1000000;
MEM[7] = 32'b0000000_00010_00001_000_00001_0100000;
MEM[8] = 32'b0000000_00010_00001_000_00001_0010000;
end
always @(posedge CLK) begin
if(memory_read_strobe) begin
memory_read_data <= MEM[memory_address[9:2]];
end
end
endmodule
and this is the bench I'm using to avoid having to post the whole processor:
`include "memory.v"
module memory_tb(
input CLK,
output reg [7:0] LED
);
reg [31:0] memory_address;
reg memory_read_strobe;
wire [31:0] memory_read_data;
reg state;
reg [31:0] pc;
memory RAM(
.CLK(CLK),
.memory_address(memory_address),
.memory_read_data(memory_read_data),
.memory_read_strobe(memory_read_strobe)
);
localparam k_state_fetch = 0;
localparam k_state_wait = 1;
assign memory_address = programme_counter;
assign memory_read_strobe = (state == k_state_fetch);
always @(posedge DIV_CLK) begin
case(state)
k_state_fetch:
state <= k_state_wait;
k_state_wait: begin
state <= k_state_fetch;
pc <= pc + 1;
end
endcase
end
clockworks #(
`ifndef BENCH
.SLOW(21)
`endif
) div_clk (
.CLK(CLK),
.DIV_CLK(DIV_CLK)
);
endmodule
module clockworks
(
input CLK, // clock pin of the board
output DIV_CLK // (optionally divided) clock for the design.
);
parameter SLOW=0;
reg [SLOW:0] slow_CLK = 0;
always @(posedge CLK) begin
slow_CLK <= slow_CLK + 1;
end
assign DIV_CLK = slow_CLK[SLOW];
endmodule
I'm running yosys with this command:
yosys -p "read_verilog hw/memory_tb.v ; synth_ice40 -top memory_tb -json memory_tb.json"
and the salient part of the output shows that no RAM is being synthesised:
Info: Device utilisation:
Info: ICESTORM_LC: 41/ 5280 0%
Info: ICESTORM_RAM: 0/ 30 0%
Info: SB_IO: 12/ 96 12%
Info: SB_GB: 2/ 8 25%
Info: ICESTORM_PLL: 0/ 1 0%
Info: SB_WARMBOOT: 0/ 1 0%
Info: ICESTORM_DSP: 0/ 8 0%
Info: ICESTORM_HFOSC: 0/ 1 0%
Info: ICESTORM_LFOSC: 0/ 1 0%
Info: SB_I2C: 0/ 2 0%
Info: SB_SPI: 0/ 2 0%
Info: IO_I3C: 0/ 2 0%
Info: SB_LEDDA_IP: 0/ 1 0%
Info: SB_RGBA_DRV: 0/ 1 0%
Info: ICESTORM_SPRAM: 0/ 4 0%
The complete yosys output is here
I have found, and I believe followed, a zipcpu guide on the subject but I am neither getting BRAM or any warnings about not inferring BRAM. Does anyone understand what it is which I'm not doing correctly?
It turns out that I didn't wire the LED output to anything, and so yosys optimised the RAM away. If I add
assign LED = memory_read_data[7:0];
to the test bench, then the RAM is correctly synthesised:
Info: Device utilisation:
Info: ICESTORM_LC: 27/ 5280 0%
Info: ICESTORM_RAM: 1/ 30 3%
Info: SB_IO: 9/ 96 9%
Info: SB_GB: 3/ 8 37%
Info: ICESTORM_PLL: 0/ 1 0%