Problem of metastability: simulation of dual port ram

i simulate Dual Port Ram Register in VHDL and have some doubts about the metastability problem.

Dual Port Ram has 2 clock signal, one for Port A , the second for Port B. In my simulation I create two processes with 2 differentes clocks.

type memory_type is array(0 to adress_width) of std_logic_vector(data_width-1 downto 0);          --> memory array
signal memory_sgnl : memory_type := (others => (others => '0'));;

begin

-- Port A
process(clk_a)
begin
if(rising_edge(clk)) then
if(rising_edge(clk_a)) then
if(we_a = '1') then
end if;
end if;
end process;

-- Port B
process(clk_b)
begin
if(rising_edge(clk)) then
if(rising_edge(clk_b)) then
if(we_b = '1') then
end if;
end if;
end process;



I have found a post here. Mr Jim Lewis made a suggestion how DP Ram with 2 clocks can be simulated. He did the same implementation. So i can conclude I did correctly.

BUT I have read We need to solve a problem metastability, because there 2 clock signal : clock time crossing.

clk_crossing: process(clk, rst)
begin
if rst ='1' then
--
a_clk_b  <= '1';
a_clk_bb <= '1';

b_clk_b  <= '1';
b_clk_bb <= '1';

elsif rising_edge(clk) then
a_clk_b   <= a_clk;
a_clk_bb  <= a_clk_b;

b_clk_b   <= b_clk;
b_clk_bb  <= b_clk_b;

end if; -- if rst ='1' then
end process clk_crossing;



and then the processes should be process(a_clk_bb ) and process(b_clk_bb )

Will be it correct? Did I understand correctly how to solve metastability question?

EDIT 1

The simulation of RAM is a "part" of SPI slave. SPI slave will send 8 bits vector data to RAM ( buffer of data). It has only one system clock and SPI clock + write_enb_signal ( FIFO is full and is ready to send data to RAM) . I thought Dual port RAm will work with system clk and write_enb_signal.

process(clk_a)
begin
if(rising_edge(clk)) then
if(rising_edge(clk_a)) then
...



in the simulation spi slave there is no additional clk signal for clk_a or clk_b...

Should I create one?

• You never should put any user logic on clock path like that, especially on FPGAs. It's mentioned in Xilinx synthesis guide. Jun 21 at 6:23
• @MituRaj process(a_clk_bb )? Jun 21 at 6:31
• The whole clk crossing process is an example for bad coding practice. Jun 21 at 6:33
• @MituRaj I have found it as an example for solving metastability problem...it was done for SPI and I2C in the similar way Jun 21 at 6:37
• @MituRaj Could Dual port ram be implemented with one clock? is it important to have different clk for ports? Jun 21 at 6:39

The correct way to implement dual port RAM, or indeed anything in FPGA, is to use one system clock, with different clock enables for the two ports.

You should never use two clocks, or events from an unsynchronised domain, unless there is absolutely no alternative, for instance one clock sourced by external equipment. Synchronise the async event as early as possible to the system clock.

Once you have two asynchronous clocks reaching the same logic, metastability is unavoidable. However it can be mitigated down to an insignificant likelihood by waiting long enough, which often requires pipelined latches, in the clock resolution logic.

Matt Parker has the amusing concept of the ten.billion.human.second.century, which is about πx1019 (28:50 in to save you watching the whole video). Once you have a chance of something occurring that's less likely than that, you can more or less assume you're not going to see it in your lifetime, and neither is anyone else. Once your metastability likelihood is less than that, some people would consider it 'solved'. But it depends on how fast your system is running, how many of them you've deployed, and what the penalty is for failure, whether you'd want a bigger number or could tolerate a smaller one. Being able to predict a failure probability though is hard. You need two points on the probability/wait_time curve, and even if the failure rate with no pipelined latches is measurable, it will often not be easily measurable with just one latch. People use increased clock rates, and carefully set up the input conditions to provoke failure, to make these measurements.

• I have read about pipelined latches. The process "clk_crossing" is an implementation of it, isnt? Jun 21 at 7:07
• The clk_crossing process is using pipelined latches. So it's doing the right thing in order to minimise problems, but it's doing it in the wrong place. It's rather like commiting a murder, and then recycling the weapon in an eco-friendly way. You're doing the right eco thing, but in the commission of a heinous clk_crossing deed. Don't do the murder. Use a single clock for the RAM. Redesign for clock enables. Jun 21 at 7:11
• @LeeLeeYa You don't necessarily need pipelined latches to drive the probability of metastability down, you just have to wait long enough. However, if your system clock period is less than the time you need to wait, then you must use a pipeline of latches to implement the wait. Jun 21 at 8:59
• What you describe is not actually dual-port RAM (two control ports each with its own clock), but a dual-issue RAM (two control ports sharing a clock). It may be useful for most of the same applications in practice, and easier to reason about... but it is not an answer to the question. Jun 21 at 15:13
• Also note that metastability also occurs in a single clock fully synchronous design, with some very-low probability which in many cases is still much higher than the target you mention. Jun 21 at 15:15