Altera_Forum
Honored Contributor
9 years agoOff by 1 error with Altera SRAM controller IP?
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.