Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem with transferring data from different clock domains using dual_port_ram

Status
Not open for further replies.

smbasim

Newbie level 4
Joined
Jun 15, 2018
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
Sri Lanka
Activity points
44
Hello everyone,
I want to transfer a frame from 143Mhz clock domain to 49Mhz clock domain to view the frames through vga,
For a test i tried to transfer a vertical and horizontal white lines to view through the vga port. But i am not getting it right.
What i expect is inK4qJ.jpg.
But what i am getting is i3hojd.jpg.
I don't know what i have done wrong. I am stuck here, If someone could help me, it would be great.

Thank you!

(All the VHD files are uploaded and the top level is "fifo.vhd". The board i am using is DE1-SoC)

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity fifo is
port(
clk : in std_logic;
HS,VS,VGACLK : out std_logic;
R,G,B : out std_logic_vector(7 downto 0));
end fifo;

architecture main of fifo is 
-----------signals----------------------
signal clk_49,clk_143 : std_logic;
signal datain, dataout : std_logic_vector(7 downto 0);
signal addr2,addr1 : integer range 0 to 2047 := 0;
signal hpos,vpos : integer range 0 to 2047 := 0;
---------------------------------------------------
component pll is
        port (
            clk_clk       : in  std_logic := 'X'; -- clk
            reset_reset_n : in  std_logic := 'X'; -- reset_n
            clk_49_clk    : out std_logic;        -- clk
            clk_143_clk   : out std_logic         -- clk
        );
end component pll;

component simple_dual_port_ram_dual_clock is
	port 
	(
		rclk	: in std_logic;
		wclk	: in std_logic;
		raddr	: in natural range 0 to 2047;
		waddr	: in natural range 0 to 2047;
		data	: in std_logic_vector(7 downto 0);
		we		: in std_logic := '1';
		q		: out std_logic_vector(7 downto 0)
	);
end component simple_dual_port_ram_dual_clock;

component sync is
	port(
		clk : in std_logic;
		data : in std_logic_vector(7 downto 0);
		hsync, vsync: out std_logic;
		R,G,B : out std_logic_vector(7 downto 0)
	);
end component sync;

begin
VGACLK <= clk_49;

u2 : component sync
		  port map (clk_49,dataout,HS,VS,R,G,B);

u0 : component pll
        port map (
            clk_clk       => clk,         --     clk.clk
            reset_reset_n => '1',         --   reset.reset_n
            clk_49_clk    => clk_49,      --  clk_49.clk
            clk_143_clk   => clk_143	   -- clk_143.clk
        ); 
u1 : component simple_dual_port_ram_dual_clock
        port map (clk_143,clk_49,addr2,addr1,datain,'1',dataout);  


process(clk_143)
begin
if(clk'event and clk='1') then
-------loop-----------------
	if(hpos<1055)then 
	hpos<=hpos+1;
	else
	hpos<=0;
		if(vpos<625)then
			vpos<=vpos+1;
			else
			vpos<=0;
		end if;
	end if;
------------------------------
	if (addr1 = addr2) then
	------do nothing-------------
	else
		if(hpos = 600 or vpos = 300) then
			datain<= (others=> '1');
		else
			datain<= (others=> '0');
		end if;
		addr1 <= addr1 + 1;
		if(addr1 = 1055)then
			addr1<=0;
		end if;
	end if;	
end if;
end process;
		  
process(clk_49)
begin
if(clk'event and clk='1') then
	addr2 <= addr2 + 1;
	if(addr2 = 1055)then
		addr2<=0;
	end if;	
end if;
end process;
		  
end main;

Code:
-- Quartus Prime VHDL Template
-- Simple Dual-Port RAM with different read/write addresses and
-- different read/write clock

library ieee;
use ieee.std_logic_1164.all;

entity simple_dual_port_ram_dual_clock is

	generic 
	(
		DATA_WIDTH : natural := 8;
		ADDR_WIDTH : natural := 11
	);

	port 
	(
		rclk	: in std_logic;
		wclk	: in std_logic;
		raddr	: in natural range 0 to 2**ADDR_WIDTH - 1;
		waddr	: in natural range 0 to 2**ADDR_WIDTH - 1;
		data	: in std_logic_vector((DATA_WIDTH-1) downto 0);
		we		: in std_logic := '1';
		q		: out std_logic_vector((DATA_WIDTH -1) downto 0)
	);

end simple_dual_port_ram_dual_clock;

architecture rtl of simple_dual_port_ram_dual_clock is

	-- Build a 2-D array type for the RAM
	subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
	type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;

	-- Declare the RAM signal.	
	signal ram : memory_t;

begin

	process(wclk)
	begin
	if(rising_edge(wclk)) then 
		if(we = '1') then
			ram(waddr) <= data;
		end if;
	end if;
	end process;

	process(rclk)
	begin
	if(rising_edge(rclk)) then 
		q <= ram(raddr);
	end if;
	end process;

end rtl;

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity sync is
port(
clk : in std_logic;
data : in std_logic_vector(7 downto 0);
hsync, vsync: out std_logic;
R,G,B : out std_logic_vector(7 downto 0));
end sync;

architecture main of sync is
signal hpos : integer range 0 to 1055:=0;
signal vpos : integer range 0 to 625:=0;
begin
process(clk)
begin
if(clk'event and clk='1')then
-----------------------------------
--loop-----------------------------
	if(hpos<1055)then 
	hpos<=hpos+1;
	else
	hpos<=0;
		if(vpos<625)then
			vpos<=vpos+1;
			else
			vpos<=0;
		end if;
	end if;
--------------------------------------
--SYNC-----------------------------------
   if(hpos<80)then
		hsync<='0';
		else
		hsync<='1';
	end if;
   if(vpos<3)then
		vsync<='0';
		else
		vsync<='1';
	end if;
--------------------------------------	
   if((hpos<240)or(hpos>1040)or(vpos<24)or(vpos>623))then
	R<=(OTHERS=>'0');
	G<=(OTHERS=>'0');
	B<=(OTHERS=>'0');
	else
	R<=data;
	G<=data;
	B<=data;
	end if;
----------------------------
end if;
end process;
end main;
 
Last edited by a moderator:

Why are you writing your own FIFO, on top of that, why are you writing a FIFO that doesn't handle the address transfer nor does it even have flags to tell you if the FIFO has gone full or empty?

This alone will fail to work correctly.
if (addr1 = addr2) then
as addr1 is on 143 MHz and addr2 is on 49 MHz. You cannot compare them without random errors occurring due to metastability and bit sampling errors due to differences in delay for every bit.
 

The fifo i am using is a template from quartus. My ultimate goal is also to change the clock domain. That is why i am using that template. Also Addr1 runs faster than addr2, so the condition "if (addr1 = addr2) then" will prevent overwriting the fifo and makes the addr1 go slower than addr2. I am new to this, that is why i am getting this struggle.
 

Use altera's DCFIFO IP, dont write your own. It crosses the clock domain safely.
Also, do you have a testbench? have you run simulations?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top