Search code examples
verilogyosysice40

Cannot get yosys to infer BRAM


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?


Solution

  • 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%