- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
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.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
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
링크가 복사됨
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
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
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
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
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Do you have further inquiries regarding this case?
No, I think I get it. Thanks.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
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
