Altera_Forum
Honored Contributor
13 years agoHelp with metastability problem
Hi,
I'm working on a vision processing based project at uni using a custom board built around a cyclone III and I am having to modify some vhdl code written by previous years students. A method for transmitting data from the board had been previously implemented but is very static and hard to modify. So just to test my code I decided to 'Hijack' an area that already writes data out. in this area, data is written to an instantiated RAM block (of type altsyncram) acting as a buffer. When this has been filled a ready signal is activated and the contents of the RAM block is transmitted via an FTDI interface. So I setup a block that for the time being fills the RAM block with hardcoded values (2 values that alternate at each clock cycle) while a valid frame is being read from the camera and then when the frame is over, I set the ready signal to active high and trigger the writing process. the data I am sending is 48 bits and has the form 8-bits : for a color label 10-bits : for x1 coordinate 10-bits : for y1 coordinate 10-bits : for x2 coordinate 10-bits : for y2 coordinate so I send the following hard coded alternating data (color_label, x1, y1, x2, y2) data1 : (4, 1, 1, 1, 1) data2 : (4, 1, 1, 1, 2) on receiving the data I get random values of either (4,1,1,1,0), (4,1,1,1,1), (4,1,1,1,2) or (4,1,1,1,3). This leads me to think that I am having a problem with metastability and I believe it has something to do with the RAM block (altsyncram) as if I just pass the values continuously to the uploader (bypassing the RAM) i get values as expected, however this is not a viable solution outside of test conditions. I have attached a picture of my block that is setting the hardcoded values and the RAM block I am writing to. The code of my block is as follows: -- INPUTS FVAL : indicates a valid frame from the camera DVAL : indicates valid data from the camera VALID_IN : indicates valid data into this block (currently unused) buffer_lock : indicates the data in the RAM is being uploaded, so can't write to RAM LINE_OBJ : the data to write out (currently unused, values are hardcoded for testing) -- OUTPUTS buffer_lock_out : used to block the data that use to be writing to the RAM (ignore this) buffer_rdy : the ready signal that starts the upload process wren : write enabled signal to the RAM block wr_addr : the address to write to RAM obj_count : the data count written to RAM (ignore this, for external purposes) wr_data : the data to write to RAMlibrary ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.obj_extraction_pkg.all;
entity OBJ_RamWriter is
port(
-- Clock Input
CLK : in std_logic;
-- Inputs
buffer_lock : in std_logic := '0';
VALID_IN : in std_logic := '0';
DVAL_IN : in std_logic := '0';
FVAL_IN : in std_logic := '0';
LINE_OBJ : in std_logic_vector(obj_wd-addr_wd-1 downto 0);
-- Outputs
buffer_lock_out : out std_logic := '0';
buffer_rdy : out std_logic := '0';
wren : out std_logic := '0';
wr_addr : out unsigned(6 downto 0);
obj_count : out unsigned(6 downto 0);
wr_data : out std_logic_vector(obj_wd-addr_wd-1 downto 0)
);
end entity;
architecture rt1 of OBJ_RamWriter is
-- Data Registers
signal lock_reg : std_logic := '0';
signal v_reg : std_logic := '0';
signal fvalid_reg : std_logic := '0';
signal line_reg : std_logic_vector(obj_wd-addr_wd-1 downto 0);
-- Internal States
signal count : unsigned(6 downto 0) := to_unsigned(0,7);
signal addr : unsigned(6 downto 0) := to_unsigned(0,7);
signal rdy_reg : std_logic := '0';
signal rdy_reg_temp : std_logic := '0';
signal odd : std_logic := '0';
-- Output registers
signal lock_out_reg : std_logic := '0';
signal valid_out_reg : std_logic := '0';
BEGIN
process (CLK)
BEGIN
if (rising_edge(CLK)) then
-- Store inputs
lock_reg <= buffer_lock;
v_reg <= '1';--VALID_IN;
if (DVAL_IN = '1' and FVAL_IN = '1') then
fvalid_reg <= '1';
else
fvalid_reg <= '0';
end if;
if (odd = '0') then
odd <= '1';
line_reg <= std_logic_vector(to_unsigned(4, 8) & to_unsigned(1,10) & to_unsigned(1,10) & to_unsigned(1,10) & to_unsigned(1,10));--LINE_OBJ;
--wr_data <= std_logic_vector(to_unsigned(4, 8) & to_unsigned(1,10) & to_unsigned(1,10) & to_unsigned(1,10) & to_unsigned(1,10));--LINE_OBJ;
else
odd <= '0';
line_reg <= std_logic_vector(to_unsigned(4, 8) & to_unsigned(1,10) & to_unsigned(1,10) & to_unsigned(1,10) & to_unsigned(2,10));
--wr_data <= std_logic_vector(to_unsigned(4, 8) & to_unsigned(2,10) & to_unsigned(2,10) & to_unsigned(2,10) & to_unsigned(2,10));--LINE_OBJ;
end if;
end if;
end process;
process (lock_reg, v_reg, fvalid_reg, line_reg)
BEGIN
if (lock_reg = '0') then -- Buffer not being read by uploader
-- Prevents any other output but lines
lock_out_reg <= '1';
if (fvalid_reg = '1') then -- Frame Data to be processed exists
rdy_reg_temp <= '0';
if (rdy_reg = '1') then -- Buffer upload complete, reset
addr <= to_unsigned(0,7);
if (v_reg = '1') then -- Valid object ready to be written to buffer
valid_out_reg <= '1';
count <= to_unsigned(1,7);
else -- No valid object
valid_out_reg <= '0';
count <= to_unsigned(0,7);
end if;
else -- Normal writting state
if (v_reg = '1' and count < to_unsigned(127,7)) then -- Valid object ready to be written to buffer
addr <= addr + 1;
count <= count + 1;
valid_out_reg <= '1';
else -- No valid object
addr <= addr;
count <= count;
valid_out_reg <= '0';
end if;
end if;
else -- No valid frame data left, start upload
rdy_reg_temp <= '1';
addr <= addr;
count <= count;
valid_out_reg <= '0';
end if;
else -- Buffer being read by uploader
lock_out_reg <= '1';
count <= count;
addr <= addr;
rdy_reg_temp <= '1';
valid_out_reg <= '0';
end if;
end process;
rdy_reg <= rdy_reg_temp;
buffer_lock_out <= lock_out_reg;
buffer_rdy <= rdy_reg_temp;
wren <= valid_out_reg;
wr_addr <= addr;
obj_count <= count;
wr_data <= line_reg;
end rt1;
I have a feeling that I may be violating the setup of hold times of the RAM block but I do not know how to verify this or how to fix it. Any ideas/suggestions would be greatly appreciated and I would be happy to provide any additional information. Thanks, Mat.