Synchronization

J

john

Hello,

Clock (clk1x) is a 100MHz clock and the VHDL program is using it to
read the SDRAM. I need to load the SDRAM with the data and then send
it to the Digital to Analog converter. The DAC works with 1MHz clock,
49 bits of data and a Tag signal which tells the DAC that a new 49 bit
data is available. I tried to divide the 100MHz clock to 1MHz and send
the data to the clock. But I am unable to see the DAC working. I
hooked up the logic analyzer and looked at the signals. The Tag who
should repeats itself after every 49 bits is not stable at all. it
repeats multiple times during the data stream and resets the DAC. My
code is given below. I am having clock synchronization problems.
Please advice. John

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

package mem is

component memTest
generic(
PIPE_EN : boolean := false; -- enable pipelined
operations
DATA_WIDTH : natural := 16; -- memory data width
ADDR_WIDTH : natural := 23; -- memory address width
BEG_TEST_1 : natural := 16#00_0000#; -- beginning test
range address
BEG_TEST_2 : natural := 16#00_0002#;
BEG_TEST_3 : natural := 16#00_0004#;
BEG_TEST_4 : natural := 16#00_0006#;
BEG_TEST_5 : natural := 16#00_0008#;
BEG_TEST_6 : natural := 16#00_0009#;
END_TEST_1 : natural := 16#3F_FFFF#;
END_TEST_2 : natural := 16#3F_FFFF#;
END_TEST_3 : natural := 16#3F_FFFF#;
END_TEST_4 : natural := 16#3F_FFFF#;
END_TEST_5 : natural := 16#3F_FFFF#;
END_TEST_6 : natural := 16#7F_FFFF# -- ending test range
address
);

port(
clk : in std_logic; -- master clock input
rst : in std_logic; -- reset
doAgain : in std_logic; -- re-do memory test
begun : in std_logic; -- memory operation begun
indicator
done : in std_logic; -- memory operation done
indicator
dIn : in std_logic_vector(DATA_WIDTH-1 downto 0); --
data from memory
rdPending: in std_logic; -- read operations in progress
indicator
rd : out std_logic; -- memory read control
signal
wr : out std_logic; -- memory write control
signal
addr : out std_logic_vector(ADDR_WIDTH-1 downto 0); --
address to memory
dOut : out std_logic_vector(DATA_WIDTH-1 downto 0); --
data to memory
progress : out std_logic_vector(1 downto 0); -- memory test
progress indicator
err : out std_logic; -- memory error flag
Logic_port: out std_logic_vector(DATA_WIDTH-1 downto 0);
Trigger : out std_logic;
-- lock_in : in std_logic;
clk1x : in std_logic;
clk_out : out std_logic;
ser_out : out std_logic;
done_1 : out std_logic;
done_2 : out std_logic;
done_3 : out std_logic;

-- Signals for Six more Phil's Chips --

ser_out_1 : out std_logic;
sclk_1 : out std_logic;
Dclk_1 : out std_logic;
Tag_1 : out std_logic;

ser_out_2 : out std_logic;
sclk_2 : out std_logic;
Dclk_2 : out std_logic;
Tag_2 : out std_logic;


ser_out_3 : out std_logic;
sclk_3 : out std_logic;
Dclk_3 : out std_logic;
Tag_3 : out std_logic;


ser_out_4 : out std_logic;
sclk_4 : out std_logic;
Dclk_4 : out std_logic;
Tag_4 : out std_logic;

ser_out_5 : out std_logic;
sclk_5 : out std_logic;
Dclk_5 : out std_logic;
Tag_5 : out std_logic

);
end component;
end package mem;

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
use WORK.common.all;
use WORK.rand.all;

entity memTest is
generic(
PIPE_EN : boolean := false; -- enable pipelined
operations
DATA_WIDTH : natural := 16; -- memory data width
ADDR_WIDTH : natural := 23; -- memory address width
BEG_TEST_1 : natural := 16#00_0000#; -- beginning test
range address
BEG_TEST_2 : natural := 16#00_0002#;
BEG_TEST_3 : natural := 16#00_0004#;
BEG_TEST_4 : natural := 16#00_0006#;
BEG_TEST_5 : natural := 16#00_0008#;
BEG_TEST_6 : natural := 16#00_0009#;
END_TEST_1 : natural := 16#3F_FFFF#;
END_TEST_2 : natural := 16#3F_FFFF#;
END_TEST_3 : natural := 16#3F_FFFF#;
END_TEST_4 : natural := 16#3F_FFFF#;
END_TEST_5 : natural := 16#3F_FFFF#;
END_TEST_6 : natural := 16#7F_FFFF# -- ending test range
address
);
port(

clk : in std_logic; -- master clock input
rst : in std_logic; -- reset
doAgain : in std_logic; -- re-do memory test
begun : in std_logic; -- memory operation begun
indicator
done : in std_logic; -- memory operation done
indicator
dIn : in std_logic_vector(DATA_WIDTH-1 downto 0); --
data from memory
rdPending : in std_logic; -- read operations in progress
indicator
rd : out std_logic; -- memory read control
signal
wr : out std_logic; -- memory write control
signal
addr : out std_logic_vector(ADDR_WIDTH-1 downto 0); --
address to memory
dOut : out std_logic_vector(DATA_WIDTH-1 downto 0); --
data to memory
progress : out std_logic_vector(1 downto 0); -- memory test
progress indicator
err : out std_logic; -- memory error flag
Logic_port : out std_logic_vector(DATA_WIDTH-1 downto 0);
Trigger : out std_logic;
clk1x : in std_logic;
clk_out : out std_logic;
ser_out : out std_logic;
done_1 : out std_logic;
done_2 : out std_logic;
done_3 : out std_logic;

-- Signals for Six more Phil's Chip --

ser_out_1 : out std_logic;
sclk_1 : out std_logic;
Dclk_1 : out std_logic;
Tag_1 : out std_logic;

ser_out_2 : out std_logic;
sclk_2 : out std_logic;
Dclk_2 : out std_logic;
Tag_2 : out std_logic;


ser_out_3 : out std_logic;
sclk_3 : out std_logic;
Dclk_3 : out std_logic;
Tag_3 : out std_logic;


ser_out_4 : out std_logic;
sclk_4 : out std_logic;
Dclk_4 : out std_logic;
Tag_4 : out std_logic;

ser_out_5 : out std_logic;
sclk_5 : out std_logic;
Dclk_5 : out std_logic;
Tag_5 : out std_logic
);
end memTest;

architecture arch of memTest is

type matrix is array ( 47 downto 0) of bit;
--states of the memory tester state machine
type testState is (
INIT,
Ser_buff_LOAD_1,
Ser_buff_LOAD_2,
Ser_buff_LOAD_3,
Ser_buff_LOAD_4,
EMPTY_PIPE,
STOP,
ser_out_state,
extra_state,
First_byte,
Second_byte,
Third_byte,
Reset_state,
Tag_state,
extra_Tag_state
);

signal state_r, state_x : testState; -- state register and next state
--registers
signal addr_r, addr_x : unsigned(addr'range);
signal err_r,err_x :std_logic;

--Internal signals
signal ld : std_logic;
signal cke: std_logic;
signal rand :std_logic_vector (dOut'range);
signal seed :std_logic_vector (dIn'range);
signal ser_buff : std_logic_vector (47 downto 0);
signal p2s_counter : unsigned (5 downto 0);
signal count_begin :std_logic;
signal count_load : std_logic;
signal d1,d2,d3 : std_logic; -- Signals to load the data buffers
signal Reset_counter : std_logic;
signal p2s: std_logic_vector (5 downto 0);
signal co : std_logic_vector (5 downto 0);
signal xser_out : std_logic;
signal Tag : std_logic;
signal clk_divider : std_logic_vector ( 10 downto 0);
signal clk_a, a,b,c,clk_b : std_logic;
signal Tag_fall,dummy_clk,clk_out_1, Tag2, t2, Tag3,
t3,D_2clk,Q_2clk : std_logic;
signal D,Q,d_1 : std_logic;
signal slow_clk : std_logic;
signal count : std_logic_vector ( 6 downto 0);
signal Tag_sig : std_logic;
signal ser_out_sig_1: std_logic;
signal ser_out_sig_2: std_logic;
signal clk_delay : std_logic;
signal Tag_out_2, Tag_out_1,Tag_out_0 : std_logic;
signal Reset_counter_0,
Reset_counter_1,final_reset,clk_synch,synch_reset,synch_reset_2 :
std_logic;
signal Reset_synch_0,Reset_synch_1,Reset_synch_2,Reset_synch_3 :
std_logic;

---Second State Machine --
Type Pulse_state is ( seek, find);
Signal status : PULSE_STATE;
Signal Pulse_out : std_logic;
Signal Pulse_out_1 : std_logic;
Signal Pulse_out_2 : std_logic;

Begin
seed <= (others => '1');-- random number seed is 111...111
u0 : randGen
generic map(
DATA_WIDTH => seed'length
)
port map(
clk => clk, -- input clock
cke => cke, -- clock-enable to control when
new random num is computed
ld => ld, -- load seed control signal
seed => seed, -- random number seed
rand => rand -- random number output from
generator
);
------------------------------------------------------------------------------------
addr <= std_logic_vector(addr_r); -- linear memory addressing
clk_b <= clk_divider(6);
done_1 <= synch_reset ;-- Tag
done_3 <= clk_synch when synch_reset ='0' else '0'; -- DCLK
clk_out <= clk_divider(5); -- SCLK

-----------------------------------------------------------------------------------
-- memory test controller state machine operations

combinatorial : process(err_r, addr_r, dIn, rand, begun, done,
rdPending, doAgain )

begin

-- default operations (do nothing unless explicitly stated in the
following case statement)
rd <= NO; -- no memory write
wr <= NO; -- no memory read
ld <= NO; -- don't load the random
number generator
cke <= NO; -- don't generate a new random
number
addr_x <= addr_r; -- next address is the same as
current address
err_x <= err_r; -- error flag is unchanged
state_x <= state_r; -- no change in memory tester
state

-- **** compute the next state and operations ****
case state_r is

------------------------------------------------------
-- initialize the memory test controller
------------------------------------------------------
when INIT =>

ld <= YES; -- load random number seed
cke <= YES; -- enable clocking of rand num
gen so seed gets loaded
addr_x <= TO_UNSIGNED(BEG_TEST_1, addr_x'length); -- load
starting mem address
err_x <= NO; -- clear memory error flag
state_x <= Ser_buff_LOAD_1; -- next go to LOAD state and write
pattern to memory
progress <= "00"; -- indicate the current controller
state
Reset_counter <= '1';
count_begin <= '0';

when Ser_buff_LOAD_1 => -- re-run the generator and
compare it to memory contents

Reset_counter <= '1';

if PIPE_EN then
rd <= YES;
if begun = YES then
addr_x <= addr_r + 1; -- increment address to check next
memory location
end if;

if addr_r = END_TEST_1 then
state_x <= EMPTY_PIPE;
end if;

if done = YES then
cke <= YES;
end if;
else

if done = NO then -- current read operation is not
complete
rd <= YES; -- keep read signal active since
memory read is not done
count_begin <='0';

else
rd <= NO;
d1 <='1'; -- Loaded first set of buffer
d2 <='0';
d3 <='0';
count_begin <='0';
state_x <= Ser_buff_LOAD_2;

if addr_r= END_TEST_1 then
state_x <= STOP; -- go to STOP state once entire
range has been checked
end if;
addr_x <= addr_r + 1; -- increment address to check next
memory location
cke <= YES;
End if;
End if;
------------------------------------
When Ser_buff_LOAD_2 =>
Reset_counter <='1';

if PIPE_EN then
rd <= YES;
if begun = YES then
addr_x <= addr_r + 1; -- increment address to check next
memory location
end if;

if addr_r = END_TEST_1 then
state_x <= EMPTY_PIPE;
end if;

if done = YES then
cke <= YES;
end if;

else

if done = NO then -- current read operation is not
complete
rd <= YES; -- keep read signal active since
memory read is not done
count_begin <='0';

else
rd <= NO;
d1 <='0';
d2 <='1'; -- Loaded Second set of buffer
d3 <='0';
count_begin <='0';
state_x <= Ser_buff_LOAD_3;

if addr_r= END_TEST_1 then
state_x <= STOP; -- go to STOP state once entire
range has been checked
end if;
addr_x <= addr_r + 1; -- increment address to check next
memory location
cke <= YES;
End if;
End if;
---------------------------------------------
When Ser_buff_LOAD_3 =>

if PIPE_EN then
rd <= YES;

if begun = YES then
addr_x <= addr_r + 1; -- increment address to check next
memory location
end if;

if addr_r = END_TEST_1 then
state_x <= EMPTY_PIPE;
end if;

if done = YES then
cke <= YES;
end if;

else

if done = NO then -- current read operation is not
complete
rd <= YES; -- keep read signal active since
memory read is not done
count_begin <='0';

else
rd <= NO;
d1 <='0';
d2 <='0';
d3 <='1'; -- Loaded Third set of buffer
count_begin <='0';
state_x <= Reset_state;

if addr_r= END_TEST_1 then
state_x <= STOP; -- go to STOP state once entire
range has been checked
end if;
addr_x <= addr_r + 1; -- increment address to check next
memory location
cke <= YES;
End if;
End if;
----------------------------------------------
when Reset_state =>

progress <= "10"; -- indicate the current
controller state
d1<='0';
d2<='0';
d3<='0';
Reset_counter <='1';
rd<=NO;
count_begin<='0';

state_x<= Tag_state;

--------------------------------------------
when Tag_state => -- Is this an extra state

d1 <= '0';
d2 <= '0';
d3 <= '0';
Reset_counter <='0';
rd<=NO;
count_begin <= '0';
state_x <= ser_out_state;
----------------------------------------
when ser_out_state =>

Reset_counter <='0';

if ( p2s_counter /= "110001") then
rd <= NO;
count_begin <= '1';
Reset_counter <='0';
state_x <= ser_out_state;

else

state_x <= Ser_buff_LOAD_1;

end if;
---------------------------------------
When EMPTY_PIPE =>
Reset_counter <='1';
if done = YES then
cke <= YES;
end if;

if rdPending = NO then
state_x <= STOP;
end if;
------------------------------------
When others =>

if doAgain = YES then
Reset_counter <='1';
ld <= YES;
cke <= YES;
addr_x <= TO_UNSIGNED (BEG_TEST_1, addr_x'length);
count_begin <='0';
state_x <= INIT;
end if;
end case;

end process;

------------------------------------
-- clk1x is the main clock generated by xess's program
update: process (clk1x)
begin
if clk1x'event and clk1x = '1' then
if rst = YES then -- main reset from xess's program
state_r <= INIT;
else
addr_r <= addr_x;
state_r <= state_x;
end if;
end if;
end process;
------------------------------------
-- Filling the Buffers with memory data
trig: process ( clk1x)
begin
if clk1x'event and clk1x = '1' then
if ( done = YES ) then
if ( d1 = '1') then
ser_buff ( 15 downto 0) <= dIn ( 15 downto 0);
--ser_buff ( 15 downto 0) <= "1010101010101010";
a <='1';
b <='0';
c <= '0';

elsif ( d2 = '1' ) then
ser_buff ( 31 downto 16 ) <= dIn ( 15 downto 0);
--ser_buff ( 31 downto 16 ) <= "1010101010101010";
a <= '0';
b <= '1';
c <= '0';

elsif ( d3 = '1') then
ser_buff ( 47 downto 32 ) <= dIn ( 15 downto 0);
--ser_buff ( 47 downto 32 ) <= "1010101010101010";
a <= '0';
b <= '0';
c <= '0';

else
a <='0';
b <='0';
c <='0';
end if;
end if;
end if;
end process;

--------------------------------------
-- Synchronizing the Reset counter of the state machine..
Reset_synch: process ( clk1x,rst)
Begin

if (rst= '1') then
clk_synch <= '0';
elsif rising_edge (clk1x) then
clk_synch <= clk_b;
end if;
end process;
-------------------------------------

serial_count : process (synch_reset , clk_synch)
begin
if ( synch_reset = '1') Then
p2s_counter <= ( others =>'0');
elsif falling_edge (clk_synch) then
p2s_counter <= p2s_counter + 1;
--ser_out<=ser_buff ( to_integer ( p2s_counter ) );
else
end if;
end process;
------------------------------------
-- Synchronizing the state machine "Reset counter" with the DCLK--
process(clk_synch, Reset_counter)
begin
If (Reset_counter = '1') Then
synch_reset_2 <='1';
elsif rising_edge (clk_synch) then
synch_reset_2 <= Reset_counter;
end if;
end process;
------------------------------------
process(clk_synch, synch_reset_2)
begin
If ( synch_reset_2 = '1') Then
synch_reset <='1';
elsif rising_edge (clk_synch) then
synch_reset <= synch_reset_2;
end if;
end process;
-----------------------------------
div : process ( rst,clk1x)
begin
If ( rst = '1') Then
clk_divider <= "00000000000";
elsIf rising_edge (clk1x) then
clk_divider <= clk_divider + 1;
end if;
end process;
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
I don't see any division by 100; I see a division by 32 (clk_out; that never gets used by the way) and a division by 64 (clk_b). How are you getting div by 100?

John
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
Why are you running your state machine running combinatorial instead of synchronous? That could be another cause of unexpected timing. Sync to your 100 MHz clock (clk1).

Side note - If you you spaces instead of tabs when you write, your code is much easier to read on this site. I learned that recently!
 
M

Mike Treseler

john said:
Clock (clk1x) is a 100MHz clock and the VHDL program is using it to
read the SDRAM. I need to load the SDRAM with the data and then send
it to the Digital to Analog converter. The DAC works with 1MHz clock,
49 bits of data and a Tag signal which tells the DAC that a new 49 bit
data is available. I tried to divide the 100MHz clock to 1MHz and send
the data to the clock. But I am unable to see the DAC working.

A 100MHz process running on the fpga ought
to be fast enough to handshake synchronously
with a 1 MHz dac.

-- Mike Treseler
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
Does the DAQ have its own 1 MHz clock, so there are two clocks and the signal is passing from one clock (100 MHz sync'd) to the other (1 MHz DAQ)? That can have metastability issues you will need to address. Or is there only one master clock (clk1) in the system?
 
A

Andy Peters

Hello,

Clock (clk1x) is a 100MHz clock and the VHDL program is using it to
read the SDRAM. I need to load the SDRAM with the data and then send
it to the Digital to Analog converter. The DAC works with 1MHz clock,
49 bits of data and a Tag signal which tells the DAC that a new 49 bit
data is available. I tried to divide the 100MHz clock to 1MHz and send
the data to the clock.  But I am unable to see the DAC working. I
hooked up the logic analyzer and looked at the signals. The Tag who
should repeats itself after every 49 bits is not stable at all. it
repeats multiple times during the data stream and resets the DAC. My
code is given below. I am having clock synchronization problems.
Please advice. John

Wow, more two-process state machine lossage.

And you've declared both numeric_std and std_logic_arith.

-a
 
A

Aiken

Did you check the DAC data sheet the SETUP and HOLD time for the DAC
you may need to Hold/Set your data to the DAC at rising/falling edge
in the DAC clock.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top