- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I have a QSYS system using a Nios II/e processor along with some vhdl modules which should be able to display pixels on a LCD display using a VGA controller. I have already managed to get the Nios II code working as well as the VGA interface.
I now seek to access the memory set by the Nios II code in VHDL to retrieve the pixel data and pass them onto the VGA interface, this should be possible with the dual access memory module in QSYS.
This is the toplevel VHDL code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY niosdisplay IS
PORT(
clk : IN STD_LOGIC;
key : IN STD_LOGIC;
pixel_clk : OUT STD_LOGIC;
red : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '1'); --red magnitude output to DAC
green : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '1'); --green magnitude output to DAC
blue : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '1'); --blue magnitude output to DAC
btn : IN STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0'); --btn pio
h_sync : OUT STD_LOGIC;
v_sync : OUT STD_LOGIC;
n_blank : OUT STD_LOGIC;
n_sync : OUT STD_LOGIC
);
END niosdisplay;
ARCHITECTURE behavior OF niosdisplay IS
COMPONENT vga_controller IS
PORT(
pixel_clk : IN STD_LOGIC; --pixel clock at frequency of VGA mode being used
reset_n : IN STD_LOGIC; --active low asycnchronous reset
h_sync : OUT STD_LOGIC; --horiztonal sync pulse
v_sync : OUT STD_LOGIC; --vertical sync pulse
disp_ena : OUT STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
column : OUT INTEGER; --horizontal pixel coordinate
row : OUT INTEGER; --vertical pixel coordinate
n_blank : OUT STD_LOGIC; --direct blacking output to DAC
n_sync : OUT STD_LOGIC --sync-on-green output to DAC
);
END COMPONENT vga_controller;
COMPONENT altpll0 IS
PORT
(
areset : IN STD_LOGIC := '0';
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC
);
END COMPONENT altpll0;
COMPONENT system is
port (
btn_pio_export : in std_logic_vector(3 downto 0) := (others => '0'); -- btn_pio.export
clk_clk : in std_logic := '0'; -- clk.clk
frame_buf_address : in std_logic_vector(16 downto 0) := (others => '0'); -- frame_buf.address
frame_buf_chipselect : in std_logic := '0'; -- .chipselect
frame_buf_clken : in std_logic := '0'; -- .clken
frame_buf_write : in std_logic := '0'; -- .write
frame_buf_readdata : out std_logic_vector(31 downto 0); -- .readdata
frame_buf_writedata : in std_logic_vector(31 downto 0) := (others => '0'); -- .writedata
frame_buf_byteenable : in std_logic_vector(3 downto 0) := (others => '0'); -- .byteenable
reset_reset_n : in std_logic := '0' -- reset.reset_n
);
END COMPONENT system;
--VGA Stuff
signal clk_138 : std_logic;
signal column : integer;
signal row : integer;
signal disp_ena : std_logic;
--Nios II Stuff
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
signal frame_buf_addr : natural range 0 to 65536 := 0;
BEGIN
u0: altpll0 port map('0', clk, clk_138);
u1: vga_controller port map(clk_138, '1', h_sync,v_sync, disp_ena, column, row, n_blank, n_sync);
u2: system port map(btn_pio_export => btn,
clk_clk => clk_138,
reset_reset_n => '1',
frame_buf_address => std_logic_vector(to_unsigned(frame_buf_addr, 17)),
frame_buf_readdata => mem_data,
frame_buf_chipselect => '0'
);
pixel_clk <= clk_138;
draw_pixel : PROCESS(clk_138)
variable count : natural range 0 to 4 := 0;
BEGIN
IF rising_edge(clk_138) then
IF disp_ena = '1' then
--IF((row > 256) and (row < 256+512) and (column > 320) and (column < 320+512)) THEN --Inside game screen
case count is
when 0 =>
red <= mem_data(31 downto 24);
blue <= mem_data(31 downto 24);
green <= mem_data(31 downto 24);
count := 1;
when 1 =>
red <= mem_data(23 downto 16);
green <= mem_data(23 downto 16);
blue <= mem_data(23 downto 16);
count := 2;
when 2 =>
red <= mem_data(15 downto 8);
green <= mem_data(15 downto 8);
blue <= mem_data(15 downto 8);
count := 3;
if(frame_buf_addr = 65535) then
frame_buf_addr <= 0;
else
frame_buf_addr <= frame_buf_addr + 1;
end if;
when 3 =>
red <= mem_data(7 downto 0);
green <= mem_data(7 downto 0);
blue <= mem_data(7 downto 0);
count := 0;
when others =>
red <= mem_data(31 downto 24);
green <= mem_data(31 downto 24);
blue <= mem_data(31 downto 24);
end case;
--ELSE --Gray color to boundary
--red <= "11111001";
--green <= "10101001";
--blue <= "10101001";
--END IF;
ELSE
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
END IF;
END IF;
END PROCESS;
END behavior;
This is the Qsys system:
The code increments the address every 4 accesses so it sets a single byte every 4 clock cycles. But for some reason the readdata port of the memory module is not changed whenever the address changes. It seems to be stuck at address 0, this results in the screen having the same 4 pixel pattern throughout the screen.
Here is a screenshot of a signal tap I did:
As is visible in the picture, the frame_buffer_readdata does not change its data to the corresponding frame_buf_addr. I have tried playing with the byteenable and chipselect signals but nothing seems to work getting the module to respond to the address change.
Does anyone have any idea what is wrong or what I am missing here?
Thanks,
Mart
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So I finally solved the issue...
The problem was that the frame_buffer address immediately changed back after 1 clock cycle. Since the memory has a delay it needs to be kept at their desired value for at least 2 clocks cycles, doing this will result in the readdata value changing in the third clock cycle. I have another post on reddit with a bit more context:
https://www.reddit.com/r/FPGA/comments/y1fkb1/problem_accessing_sdram_from_nios_iie_and_vhdl/
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you confirm the Nios is correctly writing data to the frame buffer? If you don't have the correct data in the RAM, then the data you read won't be what you expect.
- 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
Read this discussion. May be this can help you here https://community.intel.com/t5/Intel-Quartus-Prime-Software/On-Chip-uk49s-Memory-in-Qsys-Quartus/td-p/126471. If yes then please mentioned me here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I see that you managed to get the pixel pattern changing on your screen now, so may I know what is the current issue that you have?
Regards,
Kelly
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So, the pattern changes because I am setting the first byte of the memory (address 0). See this code snippet:
int main(void) {
u8* addr = FRAME_BUFFER_BASE; //Starting point of the video buffer
u8 color = 255;
*(addr) = 0xFF;
*(addr+1) = 0;
*(addr+2) = 0;
*(addr+3) = 0xFF;
while(1){}
}
this SHOULD result in pixel 1 = WHITE, pixel 2 = BLACK pixel 3 = BLACK pixel 4 = WHITE. But whenever I try to read from another address in memory, the output does not change. Because it is not responding to the address change (in VHDL). See this signal tap:
The frame_buf_addr changes but readdata field does not change into the next 32 bits. Because it does not increment it just repeats the pattern of the first 4 pixels(32 bits) throughout the whole screen
I want to cycle through the whole memory in VHDL so I can draw graphics like squares/circles.
Regards,
Mart
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hosts use byte addressing, so you should be increasing your address by 4 each time for a 32 bit data bus, but that doesn't explain the lack of change on readdata. Hmm.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Mart,
I will get back to you on why it does not increment. Thank you.
Regards,
Kelly
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just to inform you that Kelly has hand over this case to me and I will looking into this.
Could you help to share your project .qar files so I can understand better on the design?
Best Regards,
Richard Tan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So I finally solved the issue...
The problem was that the frame_buffer address immediately changed back after 1 clock cycle. Since the memory has a delay it needs to be kept at their desired value for at least 2 clocks cycles, doing this will result in the readdata value changing in the third clock cycle. I have another post on reddit with a bit more context:
https://www.reddit.com/r/FPGA/comments/y1fkb1/problem_accessing_sdram_from_nios_iie_and_vhdl/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I now seek to access the memory set by the Nios II code in VHDL to retrieve the pixel data and pass them onto the VGA interface
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Great to hear that. Sorry that I am not able to help out.
With that, I now transition this thread to community support. If you have a new question, Please login to ‘https://supporttickets.intel.com’, 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.
Best Regards,
Richard Tan
p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer or rate 9/10 survey.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page