2
\$\begingroup\$

I have designed a CPU that works in simulation using Verilator, and would now like to test it in hardware on an FPGA. A quick way to get to the testing phase would be to embed a program to run on the CPU into memory on the FPGA itself, then read instructions from it.

I have read about the $readmemh(...) function that reads data from a .mem file into some memory structure but I am not sure how to make this happen during synthesis. I tried using an initial construct but learnt that this was only run in simulation. How would I go about embedding data into the FPGA at synthesis?

In the future I would devise some way of loading a program at startup over serial or reading instructions from something like flash storage that could be programmed separately (similar to how an ATMega is programmed).

My RAM module is:

`timescale 1ns / 1ps
`define SIZE 512
`define ADDR(address) address[8:0]

module mem(
    /* verilator lint_off UNUSED */
    input [15:0] address,
    /* verilator lint_on UNUSED */
    input [31:0] data_in,
    output reg[31:0] data_out,
    input read,
    input write,
    input clk
);

reg[7:0] data[`SIZE-1:0];

always @(negedge clk) begin
    if (write) begin
        data[`ADDR(address)] <= data_in[7:0];
        data[`ADDR(address) + 1] <= data_in[15:8];
        data[`ADDR(address) + 2] <= data_in[23:16];
        data[`ADDR(address) + 3] <= data_in[31:24];
    end
    else if (read) begin
        data_out[7:0] <= data[`ADDR(address)];
        data_out[15:8] <= data[`ADDR(address) + 1];
        data_out[23:16] <= data[`ADDR(address) + 2];
        data_out[31:24] <= data[`ADDR(address) + 3];
    end
end

endmodule

The data structure is where I would like to embed the bytes from a file.

\$\endgroup\$
9
  • 2
    \$\begingroup\$ "I tried using an initial construct but learnt that this was only run in simulation" - initial blocks will work with many FPGA synthesis tools to set the power-on values of registers and memories \$\endgroup\$ Dec 31, 2019 at 16:32
  • 1
    \$\begingroup\$ See Burning bin file to FPGA. \$\endgroup\$
    – Dave Tweed
    Dec 31, 2019 at 16:40
  • 1
    \$\begingroup\$ First you need to find out if the particular FPGA block memory resource you are targeting is capable of being initialized from the bitstream, if it is, pursue the appropriate method. Some types cannot be, in which case you'd need your own logic to initialize the state, either by using hooks that let you read additional data beyond the end of the bitstream from the configuration flash, or by reading from some other form of non-volatile storage. \$\endgroup\$ Dec 31, 2019 at 17:22
  • \$\begingroup\$ Why does it have to be RAM? \$\endgroup\$ Dec 31, 2019 at 21:45
  • 1
    \$\begingroup\$ Then Tom Carpenter is right on the money: initial blocks synthesize fine for the Artix-7 line provided you're using official Xilinx tooling. Other toolchains might work as well. \$\endgroup\$
    – DonFusili
    Jan 6, 2020 at 6:47

1 Answer 1

-1
\$\begingroup\$

I realised the reason why readmemh wasn't working for me was that the size of the structure being written to has to be the same size as the data being read in. This may be a normal constraint or it could be down to my setup but it fixed the issue for me.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.