- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a Nios II system running on a DE2-115 that is connected to both the DRAM and SRAM on board. I have written a VGA driver that uses the avalon bus to fetch pixel data from either DRAM or SRAM, depending on the address stored in a register. The system works flawlessly when reading from DRAM. However, when I change the address to point at the SRAM chip instead, the output on the monitor shifts right by 1 pixel. 1 Pixel is 16 bits, the word size of the SRAM chip.
Memory is written by the Nios II core and read by this simple module I wrote:module vga_dram_master(
//clk domain
input clk,
input resetn,
input start,
input read_from_addr,
//avalon master for accessing SDRAM
output master_address,
output master_read,
input master_read_data,
input master_wait_request,
input master_read_data_valid,
//VGA_CLK domain
input VGA_CLK,
input read_pixel,
output pixel_out
);
//draw green on the screen if the fifo bottoms out
wire data_out;
assign pixel_out = rdempty ? 16'h03E0 : data_out;
//fifo to buffer data and bridge clock domains
wire rdempty, wrfull;
wire wrusedw;
vga_pixel F1(!resetn | start, master_read_data, VGA_CLK, read_pixel, clk, master_read_data_valid, data_out, rdempty, wrfull, wrusedw);
//pipelined access
assign master_address = currAddress;
assign master_read = !wrusedw && (wordsRead < 19'd480000) && (currAddress != 0);
reg currAddress;
reg wordsRead;
always @ (posedge clk or negedge resetn) begin
if(!resetn) begin
currAddress <= 32'd0;
wordsRead <= 19'd0;
end else begin
if (start) begin
currAddress <= read_from_addr;
wordsRead <= 19'd0;
end else if (!master_wait_request && master_read) begin
wordsRead <= wordsRead + 1'd1;
currAddress <= currAddress + 2'd2;
end
end
end
endmodule
I have poured over this code looking for mistakes, but I haven't found any. And, everything works perfectly when accessing DRAM! Here is a simple program I wrote for the Nios Core to demonstrate the problem. I can flick the switch back and forth and see the image on monitor move by 1 pixel.
int main(void) {
uint16_t *SRAM = (uint16_t*)0x20000000;
uint16_t *DRAM = (uint16_t*)0x08000000;
VGA = 0; //disable the screen for a second
//draw the same gradient background into both buffers
gradient(SRAM);
gradient(DRAM);
flush_dcache();
//this commented line fixes the issue. But why is it happening in the first place!!!?!?
//SRAM++;
uint16_t* buff = {SRAM , DRAM };
while(1) {
//wait for screen refresh
while(!VGA);
//read from DRAM or SRAM based on 0th switch
VGA = (uint32_t)buff & 1];
}
return 0;
}
Really unsure what is happening here.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Have you tried memory testing the SRAM using Nios by itself? It almost sounds like the off-chip timings are incorrect and you are reading data too late.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Have you tried memory testing the SRAM using Nios by itself? It almost sounds like the off-chip timings are incorrect and you are reading data too late. --- Quote End --- Talking about timings made me check my timequest settings, they were wrong. After fixing them, I'm now failing timing with a Recovery path between read_from_addr on the clk domain and the output of the VGA pixel fifo (from the verilog in the first post) slack: -2.156 ns from_node: nios2:u0|VGA_Controller:vga_controller|fbAddr[7] to_node: nios2:u0|VGA_Controller:vga_controller|VGA_driver:VGA0|vga_dram_master:DM0|vga_pixel:F1|dcfifo_mixed_widths:dcfifo_mixed_widths_component|dcfifo_c1l1:auto_generated|altsyncram_mv61:fifo_ram|q_b[0] launch clock: P0|altpll_component|auto_generated|pll1|clk[0] (my 90 MHz system clock) latch clock: P0|altpll_component|auto_generated|pll1|clk[2] (the VGA pixel clock - 40 MHz) I don't really understand what is happening here - I have the register 'currAddress' in between the input 'read_from_addr' (which is driven by fbAddr). So why is timing failing on this path, when it shouldn't even exist? Shouldn't there be a node 'currAddress' in the middle of that path? The SRAM issue is probably a symptom of this problem - when I was running the FPGA again today, the offset was different.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What does the full path show in Timequest? It should show you all the hops between the from_node and the to_node. A recovery timing failure means that an asynchronous signal is arriving too late to the latch destination. The full path might show why the launching address has an asynchronous path to the output of the FIFO RAM. I suspect the full path will look something like this: fbAddr[7] --> Qsys decode logic --> rdreq of DCFIFO --> q_b[0] but I'm not sure why DCFIFO would have an asynchronous load/set/reset in this case dependent on the read request coming at it though.
Did you recompile the design after making the timing changes? If not I would close the Quartus project, delete the /db directories, then recompile because it could be that the fitter spent so much time fixing a setup issue that it introduced recovery failures and re-running the fitter might fix that.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page