- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi. I'm using the ROM: 1-PORT in the IP Catalog. I've been unable to find a code example of accessing that on-chip memory. I hope someone here can help.
The IP Catalog wizard generates code for a module:
module rom (
address,
clock,
q);
input [10:0] address;
input clock;
output [7:0] q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri1 clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [7:0] sub_wire0;
wire [7:0] q = sub_wire0[7:0];
altsyncram altsyncram_component (
.address_a (address),
.clock0 (clock),
.q_a (sub_wire0),
.aclr0 (1'b0),
.aclr1 (1'b0),
.address_b (1'b1),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_a ({8{1'b1}}),
.data_b (1'b1),
.eccstatus (),
.q_b (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_a (1'b0),
.wren_b (1'b0));
defparam
altsyncram_component.address_aclr_a = "NONE",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
`ifdef NO_PLI
altsyncram_component.init_file = "G:/My Drive/microcode1.rif"
`else
altsyncram_component.init_file = "G:/My Drive/microcode1.hex"
`endif
,
altsyncram_component.intended_device_family = "MAX 10",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2048,
altsyncram_component.operation_mode = "ROM",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.widthad_a = 11,
altsyncram_component.width_a = 8,
altsyncram_component.width_byteena_a = 1;
endmodule
and then I instantiate in my own Verilog code:
rom rom_inst (.address ( address ), .clock ( clock ), .q ( q ));
What I don't understand is what q should be. Should it be 'reg [7:0] q;' or 'wire [7:0] q;'?
It seems to me, it would have to be a reg, especially since we're using a clock to fetch memory. But look at lines 12-18 in the generated module:
12 wire [7:0] sub_wire0;
13 wire [7:0] q = sub_wire0[7:0];
14
15 altsyncram altsyncram_component (
16 .address_a (address),
17 .clock0 (clock),
18 .q_a (sub_wire0),
It's using a wire to receive the memory contents! I would've thought that, inside altsyncram, there's an always block that, on the rising edge of clock0, reads the memory contents into a register. But a wire makes me think it's just combinational.
And what does that mean for my code? Do I need an always block clocking the rom module's q output into a register? And when should I do that? I assume I cannot trust that q has valid data on it, at the same clock rising edge that triggered the memory read. I need to wait for the memory access time, right?
Thank you for your help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should declare the output q as a wire, because the ROM module already registers the output internally.
You do not need to add your own always @(posedge clk) just to capture q, unless you want to add pipeline stages or synchronize it further.
The altsyncram component is configured with:
altsyncram_component.outdata_reg_a = "CLOCK0"
This means the output is registered on the rising edge of clock0 inside the IP — so the ROM fetches data synchronously, with output changes one clock cycle after the address is applied.
So even though q is declared as a wire, it is driven by a register inside the ROM IP. That’s why your code can simply declare:
wire [7:0] q;
rom rom_inst (
.address (address),
.clock (clock),
.q (q)
);
And it should works exactly as a synchronous ROM should.
So yes — you're absolutely right: you cannot use q on the same clock edge that you apply the address. You need to wait one clock cycle.
Regards,
Richard Tan
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should declare the output q as a wire, because the ROM module already registers the output internally.
You do not need to add your own always @(posedge clk) just to capture q, unless you want to add pipeline stages or synchronize it further.
The altsyncram component is configured with:
altsyncram_component.outdata_reg_a = "CLOCK0"
This means the output is registered on the rising edge of clock0 inside the IP — so the ROM fetches data synchronously, with output changes one clock cycle after the address is applied.
So even though q is declared as a wire, it is driven by a register inside the ROM IP. That’s why your code can simply declare:
wire [7:0] q;
rom rom_inst (
.address (address),
.clock (clock),
.q (q)
);
And it should works exactly as a synchronous ROM should.
So yes — you're absolutely right: you cannot use q on the same clock edge that you apply the address. You need to wait one clock cycle.
Regards,
Richard Tan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
small correction to above description.
Internal block RAM doesn't necessarily register RAM/ROM output. It always registers memory address, write data and related control signals, output register is optional and controlled by parameter outdata_reg_a/b which can be UNREGISTERED, CLOCK0 or CLOCK1.
Respectively RAM/ROM output has either 1 or 2 clock cycles latency.
Using "wire" to connect memory output port q should work for both configurations.
Regards
Frank
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Do you have further inquiries regarding this case?
No, I think I get it. Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the confirmation.
Now, I will transitioning this thread to community support. If you have any further questions or concerns, please don't hesitate to reach out. Please login to https://supporttickets.intel.com/s/?language=en_US , view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support.
The community users will be able to help you on your follow-up questions.
Thank you and have a great day!
Best Regards,
Richard Tan

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page