- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm writing a simple RAM and VGA testing module.
At first data gets written to the SDRAM (repeatedly 0 to 4095) and then it's read from the sdram and written to a FIFO to show it as pixels on the 4 bit VGA.
Because it didn't work properly I analyzed it in Signal Tap.
The expected output would be a 0 at read_pointer 0, a 10 at read_pointer 10 and so on.
At first the outputs seemed random, but I realized that I forgot the phase shift in the sdram clock. Now it's still wrong but in another, maybe better way.
I extracted the phase shift from the SDRAM test application that is delivered together with the board.
The error now is that the output numbers go up as expected, but the timing is wrong. While the readdatavalid signal is HIGH the data is obviously not correct but old.
As you can see in the Signal Tap screenshot, the 1 as ram output is visible when the read_pointer hits 4 but the ram_rdval signal is always high thus I can't trust it.
You can also see that the rdval signal is low at read_pointer 0 until the 0 arrives at the output but it doesnt go low afterwards.
I can't find the error and don't have starting point. Is it a wrongly tuned PLL? Is there some fault in my sdram controller config?
I'm using Quartus 20.1 lite and a DE10-lite board that uses a 10M50DAF484C7G FPGA and a issi 45S16320d sdram.
I can't use a newer Quartus version because the SDRAM Controller component was moved to the paid version.
Code of the main entity:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity ram_vga_demonstrator is port ( clock_50 : in std_logic; reset_n : in std_logic; ------------------SDRAM--------------------------- dram_addr : out std_logic_vector(12 downto 0); dram_ba : out std_logic_vector(1 downto 0); dram_cas_n : out std_logic; dram_cke : out std_logic; dram_clk : out std_logic; dram_cs_n : out std_logic; dram_dq : inout std_logic_vector(15 downto 0); dram_ras_n : out std_logic; dram_we_n : out std_logic; dram_ldqm : out std_logic; dram_udqm : out std_logic; -------------------VGA---------------------------- h_sync : out std_logic; v_sync : out std_logic; valid_pixel : out std_logic; vga_out : out std_logic_vector(11 downto 0); ----------------- flags ----------------------------- wr_full : out std_logic; rd_empty : out std_logic; ram_rdval : out std_logic; ---------------------------------------------------- data_out : out std_logic_vector(15 downto 0); data_in : in std_logic_vector(9 downto 0) ); end entity ram_vga_demonstrator; architecture arch of ram_vga_demonstrator is type modes is (read_t, write_t); ----------------- clocks ------------------------------ signal clk143_s : std_logic; signal clk25_175_s : std_logic; signal clk_143_shift_s : std_logic; --! Signal zur Versorgnung von Signaltap ------------------sdram-------------------------------- signal mode_s : modes := write_t; signal sdram_addr_s : std_logic_vector(24 downto 0); signal sdram_be_n_s : std_logic_vector(1 downto 0); signal sdram_cs_s : std_logic; signal sdram_rdval_s, sdram_wait_s : std_logic; signal sdram_re_n_s, sdram_we_n_s : std_logic; signal sdram_readdata_s, sdram_writedata_s : std_logic_vector(15 downto 0); signal dram_dqm_s : std_logic_vector(1 downto 0); signal sdram_out_data_s : std_logic_vector(15 downto 0); -----------------fifo------------------------------------- signal fifo_data_s : std_logic_vector(15 downto 0); -- signal fifo_rdclk_s : std_logic; signal fifo_rdreq_s : std_logic; -- signal fifo_wrclk_s : std_logic; signal fifo_wrreq_s : std_logic; signal fifo_q_s : std_logic_vector(15 downto 0); signal fifo_rdempty_s : std_logic; signal fifo_wrfull_s : std_logic; signal fifo_wrusedw_s : std_logic_vector(7 downto 0); signal fifo_rdusedw_s : std_logic_vector(7 downto 0); signal fifo_wralmostfull_s : std_logic; signal fifo_rd_almostempty_s : std_logic; -------------------vga------------------------------------- signal valid_pixel_s : std_logic; signal pixel_data_s : std_logic_vector(11 downto 0); ---------------app----------------------------------- signal ram_write_pointer_s : integer range 0 to 307199; -- 480*640 = 307.200 signal ram_read_pointer_s : integer range -1 to 307199; -- 480*640 = 307.200 signal ram_write_ready_s : std_logic; signal vga_out_almost_finished_s : std_logic; signal rgb_count_s : integer range 0 to 4094; component ramsys is port ( clk_clk : in std_logic := 'X'; clk_system_clk : out std_logic; clk_25_175_clk : out std_logic; reset_reset_n : in std_logic := 'X'; sdram_address : in std_logic_vector(24 downto 0) := (others => 'X'); sdram_byteenable_n : in std_logic_vector(1 downto 0) := (others => 'X'); sdram_chipselect : in std_logic := 'X'; sdram_writedata : in std_logic_vector(15 downto 0) := (others => 'X'); sdram_read_n : in std_logic := 'X'; sdram_write_n : in std_logic := 'X'; sdram_readdata : out std_logic_vector(15 downto 0); sdram_readdatavalid : out std_logic; sdram_waitrequest : out std_logic; wire_addr : out std_logic_vector(12 downto 0); wire_ba : out std_logic_vector(1 downto 0); wire_cas_n : out std_logic; wire_cke : out std_logic; wire_cs_n : out std_logic; wire_dq : inout std_logic_vector(15 downto 0) := (others => 'X'); wire_dqm : out std_logic_vector(1 downto 0); wire_ras_n : out std_logic; wire_we_n : out std_logic; clk_sdram_clk : out std_logic ); end component ramsys; component fifo is port ( data : in std_logic_vector(15 downto 0); rdclk : in std_logic; rdreq : in std_logic; wrclk : in std_logic; wrreq : in std_logic; q : out std_logic_vector(15 downto 0); rdempty : out std_logic; wrfull : out std_logic; wrusedw : out std_logic_vector(7 downto 0); rdusedw : out std_logic_vector(7 downto 0) ); end component fifo; component vga_controller is port ( clock_25 : in std_logic; reset_n : in std_logic; h_sync : out std_logic; v_sync : out std_logic; valid_pixel : out std_logic; data_in : in std_logic_vector(11 downto 0); data_out : out std_logic_vector(11 downto 0) ); end component vga_controller; begin u0 : component ramsys port map ( clk_clk => clock_50, reset_reset_n => reset_n, clk_system_clk => clk_system_s, clk_25_175_clk => clk25_175_s, clk_sdram_clk => clk_sdram_s, wire_addr => dram_addr, wire_ba => dram_ba, wire_cas_n => dram_cas_n, wire_cke => dram_cke, wire_cs_n => dram_cs_n, wire_dq => dram_dq, wire_dqm => dram_dqm_s, wire_ras_n => dram_ras_n, wire_we_n => dram_we_n, sdram_address => sdram_addr_s, sdram_byteenable_n => sdram_be_n_s, sdram_chipselect => sdram_cs_s, sdram_writedata => sdram_writedata_s, sdram_read_n => sdram_re_n_s, sdram_write_n => sdram_we_n_s, sdram_readdata => sdram_readdata_s, sdram_readdatavalid => sdram_rdval_s, sdram_waitrequest => sdram_wait_s ); u1 : component fifo port map ( data => sdram_out_data_s, rdclk => clk25_175_s, rdreq => fifo_rdreq_s, wrclk => clk_system_s, wrreq => fifo_wrreq_s, q => fifo_q_s, rdempty => fifo_rdempty_s, wrfull => fifo_wrfull_s, wrusedw => fifo_wrusedw_s, rdusedw => fifo_rdusedw_s ); u2 : component vga_controller port map ( clock_25 => clk25_175_s, reset_n => reset_n, h_sync => h_sync, v_sync => v_sync, valid_pixel => valid_pixel_s, data_in => pixel_data_s, data_out => vga_out ); dram_ldqm <= dram_dqm_s(0); dram_udqm <= dram_dqm_s(1); dram_clk <= clk_sdram_s; sdram_cs_s <= '1'; sdram_be_n_s <= "00"; data_out <= sdram_readdata_s; p_ram_flag : process (sdram_wait_s, ram_read_pointer_s) is begin end process p_ram_flag; p_ram : process (clk_system_s) is begin if rising_edge(clk_system_s) then case mode_s is when write_t => if (sdram_wait_s = '0') then sdram_we_n_s <= '0'; sdram_writedata_s <= "0000" & std_logic_vector(to_unsigned(rgb_count_s, 12)); if (rgb_count_s < 4095) then rgb_count_s <= rgb_count_s + 1; else rgb_count_s <= 0; end if; sdram_addr_s(24 downto 0) <= std_logic_vector(to_unsigned(ram_write_pointer_s, sdram_addr_s'length)); if (ram_write_pointer_s < 307199) then ram_write_pointer_s <= ram_write_pointer_s + 1; else ram_write_pointer_s <= 0; ram_read_pointer_s <= 0; mode_s <= read_t; end if; end if; when read_t => sdram_we_n_s <= '1'; sdram_addr_s(24 downto 0) <= std_logic_vector(to_unsigned(ram_read_pointer_s, sdram_addr_s'length)); if (sdram_rdval_s = '1' and fifo_wrfull_s = '0') then fifo_wrreq_s <= '1'; sdram_out_data_s <= sdram_readdata_s; if (ram_read_pointer_s < 307199) then ram_read_pointer_s <= ram_read_pointer_s + 1; else ram_write_pointer_s <= 0; ram_read_pointer_s <= 0; mode_s <= write_t; end if; else fifo_wrreq_s <= '0'; end if; end case; end if; end process p_ram; vga : process (clk25_175_s) is begin if rising_edge(clk25_175_s) then if (fifo_rdempty_s = '0' and valid_pixel_s = '1') then fifo_rdreq_s <= '1'; pixel_data_s <= fifo_q_s(11 downto 0); else fifo_rdreq_s <= '0'; end if; end if; end process vga; wr_full <= fifo_wrfull_s; rd_empty <= fifo_rdempty_s; ram_rdval <= sdram_rdval_s; end architecture arch;
qsys config:
PLL config:
SDRAM Controller IP config:
qsys output
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Tim,
I'm not really familiar with this application.
Usually I will always checking the timing parameter in the IP.
Does the example design working normally to verify the SDRAM is working?
Regards,
Adzim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Adzim,
thanks for your answer!
Some flaw in my timing settings was my first idea. I checked it twice and couldn't find one. I was hoping that somebody could take a look at my settings to see if I miss something. (Visible in the last screenshots).
That's the SDRAM mounted on the board:
And that's the doc I used (it's the online version of the pdf attached to the CD): https://www.issi.com/WW/pdf/42-45R-S_86400D-16320D-32160D.pdf
While writing this I realized that on the photo there is an 'F' as last character visible not a 'D' as in the CD docs. I couldn't spot any difference timing wise, but to be sure that's the one with an 'F':
https://www.issi.com/WW/pdf/42-45R-S_86400F-16320F.pdf
I want to point out that the "only" problem is that the read valid signal is not reliable. The data itself seems to be correct.
I write values from 0 to 4095 and I get values from 0 to 4095, but I would expect the read valid signal to go down one clock cycle after one value was spit out and only go on again when the next one is there.
As you can see in the screenshot of Signal Tap, the read valid signal stays high although there is still the first 0 visible.
Am I misunderstanding the meaning of readvalid?
I just tried the "SDRAM_RTL_Test" design and I suppose it works as expected.
LEDR 0 is on constantly .
LEDR 1 blinks at first and then stops to be constantly on too.
LEDR 2 blinks all time
I couldn't understand the purpose of LEDR 0 but as far as I understood, LEDR 1 blinks as long as the test runs and then is either constantly on to show success (or goes off to show failure).
LEDR seems to be a heartbeat and is only constantly on if KEY 0 is pressed.
regards,
Tim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Tim,
I think there is a Manual that you can refer to run the test. It's should explain the purpose of LED and behavior of the SDRAM.
I think the readvalid signal will go high after the read signal is go high. It's will indicate the data is valid and available .
Regards,
Adzim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Adzim,
that's true! The problem is that the readvalid signal should go down if the next value isn't ready yet and that doesn't seem to happen.
Although I found another solution using a completely different controller, I would be interested in the cause of the issue.
The settings of the IP are so simple, I would consider it as foolproof. If there is any chance that this is not an issue caused by me but some "bug" in the IP it may be interesting to investigate it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have had some similar issues, my timing and waveforms are all correct though nothing is returned when after a read cycle (even when read valid is high). On a forum I saw that the Avalon-MM interface could have a minimum burst transfer for the IP core though the official documentation does not say any of this and is not great.

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