You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to initialize a memory block using $readmemh, and I don't want to do the initialization in the module defining the ram, but in my top module. Here's a complete but cut down example:
module ram_unit(input clk, input rst,
input cyc, input stb,
input we, output ack,
input [SIZE-1:0] adr,
input [63:0] dat_write,
output reg [63:0] dat_read);
parameter SIZE = 3; // Address size
reg [63:0] mem [0:(1 << SIZE)-1];
integer i;
// Always completes in a single cycle.
assign ack = 1;
// Written this way due to
// https://github.com/cliffordwolf/yosys/issues/335
always @(posedge clk)
if (cyc & stb & ~we) begin
dat_read <= mem[adr];
end
always @(posedge clk)
if (cyc & stb & we) begin
mem[adr] <= dat_write;
end
endmodule
module main(input clk);
parameter SIZE = 3;
reg rst;
reg [SIZE-1:0] adr;
reg cyc;
reg stb;
reg we;
wire ack;
reg [63:0] dat_write;
wire [63:0] dat_read;
ram_unit #(SIZE)
ram(clk, rst, cyc, stb, we, ack,
adr, dat_write, dat_read);
initial begin
$readmemh("/dev/null", ram.mem);
end
endmodule
This is accepted by iverilog -Wall, but not by yosys:
$ yosys -q -f verilog -p synth_ice40 readmemh-1.vl
ERROR: Failed to evaluate system function `\$readmemh' with non-memory 2nd argument at readmemh-1.vl:43.
As a work-around, I tried changing the initial block to read into a locally defined memory, and then copying it to the target memory, like this:
module ram_unit(input clk, input rst,
input cyc, input stb,
input we, output ack,
input [SIZE-1:0] adr,
input [63:0] dat_write,
output reg [63:0] dat_read);
parameter SIZE = 3; // Address size
reg [63:0] mem [0:(1 << SIZE)-1];
integer i;
// Always completes in a single cycle.
assign ack = 1;
// Written this way due to
// https://github.com/cliffordwolf/yosys/issues/335
always @(posedge clk)
if (cyc & stb & ~we) begin
dat_read <= mem[adr];
end
always @(posedge clk)
if (cyc & stb & we) begin
mem[adr] <= dat_write;
end
endmodule
module main(input clk);
parameter SIZE = 3;
reg rst;
reg [SIZE-1:0] adr;
reg cyc;
reg stb;
reg we;
wire ack;
reg [63:0] dat_write;
wire [63:0] dat_read;
reg [63:0] init_mem [0:(1 << SIZE)-1];
integer i;
ram_unit #(SIZE)
ram(clk, rst, cyc, stb, we, ack,
adr, dat_write, dat_read);
initial begin
$readmemh("/dev/null", init_mem);
for (i = 0; i < (1<<SIZE); i = i + 1)
ram.mem[i] = init_mem[i];
end
endmodule
This is also accepted by iverilog -Wall, with yosys I get warnings making me think it doesn't quite work:
$ yosys -q -f verilog -p synth_ice40 readmemh-2.vl
Warning: Identifier `\ram.mem' is implicitly declared at readmemh-2.vl:48.
Warning: Range select out of bounds on signal `\ram.mem' at readmemh-2.vl:48: Setting result bit to undef.
Warning: Range select out of bounds on signal `\ram.mem' at readmemh-2.vl:48: Setting result bit to undef.
Warning: Range select out of bounds on signal `\ram.mem' at readmemh-2.vl:48: Setting result bit to undef.
Warning: Range select out of bounds on signal `\ram.mem' at readmemh-2.vl:48: Setting result bit to undef.
Suggestions for better workarounds appreciated.
Best regards,
/Niels Möller
(I tried the "insert code" button this time, but indentation still looks very bad in the preview. Sorry about that).
The text was updated successfully, but these errors were encountered:
I'm trying to initialize a memory block using $readmemh, and I don't want to do the initialization in the module defining the ram, but in my top module.
This only works in simulation. In synthesizable verilog hierarchical references are forbidden. No synthesis tool would (or should) accept this code.
(I tried the "insert code" button this time, but indentation still looks very bad in the preview. Sorry about that).
Thanks for the quick response. What's the recommended way to separate initial contents of the memory from the module implementing it, then?
I could try passing the file name (string) as a module parameter (but that's not good enough for simulation, where I want to use a command line argument (iverilog $value$plusargs) to specify the file to read), or I could use the preprocessor.
I'm aware of the icebram tool, but at the moment I'm looking for something simpler, and ideally, some way which works for both synthesis and simulation.
Filenames in module parameter or using a preprocessor define are usual methods to do that.
For simulation you can also "overwrite" the default contents by running initial $readmemh(...); in the module itself for the default memory contents, and then run another $readmemh() in your test bench slightly delayed so it will overwrite the contents set by the initial block in the module.
I'm trying to initialize a memory block using $readmemh, and I don't want to do the initialization in the module defining the ram, but in my top module. Here's a complete but cut down example:
This is accepted by iverilog -Wall, but not by yosys:
As a work-around, I tried changing the initial block to read into a locally defined memory, and then copying it to the target memory, like this:
This is also accepted by iverilog -Wall, with yosys I get warnings making me think it doesn't quite work:
Suggestions for better workarounds appreciated.
Best regards,
/Niels Möller
(I tried the "insert code" button this time, but indentation still looks very bad in the preview. Sorry about that).
The text was updated successfully, but these errors were encountered: