Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17249 Discussions

VHDL for Double Data Rate registers?

Altera_Forum
Honored Contributor II
5,800 Views

Hello, 

 

I'm writing some code for picking up nibbles at double data rate, then assembling the pieces into a byte for clocking out. Here's my code: 

 

-- Assemble nibbles into byte PROCESS(clk, reset) BEGIN IF (reset = '1') THEN reg_DATA_OUT <= "UUUUUUUU"; final_reg_DATA_OUT <= "UUUUUUUU"; -- In Gb mode, pick up least significant nibble on rising edge ELSIF (clk'event AND clk = '1') THEN reg_DATA_OUT(3 downto 0) <= data_in; -- In Gb mode, pick up most significant nibble on falling edge ELSIF (clk'event AND clk = '0') THEN final_reg_DATA_OUT <= reg_DATA_OUT; IF (gb = '1') THEN reg_DATA_OUT(7 downto 4) <= data_in; ELSE -- If not Gb mode, shift data to assemble on alternating rising edge reg_DATA_OUT(7 downto 4) <= reg_DATA_OUT(3 downto 0); END IF; END IF; END PROCESS; DATA_OUT <= final_reg_DATA_OUT;  

 

 

RTL Simulation works fine, however I get some Design Assistant warnings: 

 

 

Rule C106: Clock signal source should not drive registers triggered by different clock 

Positive edge destination node(s) list reg_DATA_OUT[0] 

Positive edge destination node(s) list reg_DATA_OUT[1] 

Positive edge destination node(s) list reg_DATA_OUT[2] 

Positive edge destination node(s) list reg_DATA_OUT[3] 

Negative edge destination node(s) list final_reg_DATA_OUT[0] 

Negative edge destination node(s) list reg_DATA_OUT[4] 

Negative edge destination node(s) list final_reg_DATA_OUT[1] 

Negative edge destination node(s) list reg_DATA_OUT[5] 

Negative edge destination node(s) list final_reg_DATA_OUT[2] 

Negative edge destination node(s) list reg_DATA_OUT[6] 

Negative edge destination node(s) list final_reg_DATA_OUT[3] 

Negative edge destination node(s) list reg_DATA_OUT[7] 

 

Is there better ways of doing this? Preferably not using ALTDDIO_IN. 

 

 

 

This does actually raise a fundamental question, I might have gotten it wrong... 

 

Is it bad or incorrect to "set registers" on one edge, and clock output of the same registers into other modules on the opposite edge? :confused: 

 

 

Best regards, 

 

M.
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
4,104 Views

It's ok to have transfers between the two clock edges -- the tools can analyze the situation. 

I don't see nothing wrong with your VHDL either, although I usually prefer to use two different processes for each edge. 

 

If those signal's are I/Os, it's adviseable to use alt_ddio. Otherwise, Quartus will not use the registers in the I/O cells.
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

 

--- Quote Start ---  

It's ok to have transfers between the two clock edges -- the tools can analyze the situation. 

I don't see nothing wrong with your VHDL either, although I usually prefer to use two different processes for each edge. 

--- Quote End ---  

 

 

You can't drive a signal from two processes. 

 

Kevin Jennings
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

You can't have a FF that's driven by both clock edges either. :) 

 

What I meant is when modeling DDR stuff, I prefer to use one process for the FFs driven for the rising edge and another process for the FFs driven by the falling edge. 

Though, I don't see anything wrong with using just a single process as mortenk used.
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

Yeah, one edge driving one set of registers, another driving the other. 

 

This is what it looks like deep inside the altddio_in function, which is similar to what my initial VHDL generated: 

 

http://s7.postimage.org/xcltmewe3/Capture_DDR.png  

 

I've included a "Data Valid" signal to simplify things a bit. 

 

-- Assemble nibbles into byte PROCESS(clk, reset) BEGIN IF (reset = '1') THEN reg_DATA_OUT <= "UUUUUUUU"; reg_DV <= '0'; -- In Gb mode, pick up least significant nibble on rising edge ELSIF (clk'event AND clk = '1') THEN IF (gb = '1') THEN reg_DATA_OUT(3 downto 0) <= dataout_h_sig(3 downto 0); reg_DATA_OUT(7 downto 4) <= dataout_l_sig(3 downto 0); ELSE -- If not Gb mode, shift data to assemble on alternating rising edge reg_DATA_OUT(7 downto 4) <= reg_DATA_OUT(3 downto 0); END IF; reg_DV <= dataout_h_sig(4); END IF; END PROCESS; DATA_OUT <= reg_DATA_OUT; DV <= reg_DV;  

 

 

Which behaves like this 

http://s15.postimage.org/lvgyb0ptn/Capture_RTL.png  

 

 

The "byte" (reg_DATA_OUT) is valid (reg_DV high) and "stable" at the falling edge of the clock - so I'm clocking it into a FIFO there. 

 

Which brings me back to my initial question, Is this good design practice? 

I could clock it in on rising edge also, but there is setup and hold times of registers that might complicate things, right? reg_DATA_OUT is changing at rising edge, which is why I should not do it there? 

 

 

Thanks for helping out btw :)
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

It's not a bad practice. 

 

The only thing you have to keep in mind is that when you have a register launching it's output on the rising edge feeding into another register which is capturing it's input in the falling edge (or vice-versa), the time available for signal propagation is cut into half. 

 

So, keep those situations to a minimum and avoid putting complex logic in those paths. 

 

But, as long the design passes timing analysis, you're OK.
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

Hmz... async FIFO on Cyclone IV/E at 125 MHz seems to be a bit of a challenge, but I believe I've managed somehow. Barely... 

 

I hooked up a PLL to the 125 MHz RGMII ENET_RX clock, then derived two clocks with 2 and 4 ns skew as data is edge aligned in nibbles. 

 

My +2 ns clock grabs the DDR data, assembles the bytes and sets WE on the FIFO. 

My +4 clock is used as write clock on the FIFO. 

 

 

reg_DV is the FIFO write enable: 

http://s15.postimage.org/8v1zn1spn/Capture_Timing.png  

 

RTL View of the DDR to FIFO path: 

http://s8.postimage.org/iosr03479/Capture_RTL.png  

 

As of now I've used TimeQuest to generate the PLL related clocks in the SDC. 

When compiling it reports timing requirements as met. 

 

 

 

Gate level sim checks out in the "Fast -M 1.2V 0 Model", but the two Slow modes look like crap. What are these "Operating modes" really? External conditions of the FPGA? 

 

 

 

Am I approaching this the right way? Sorry about my n00bish questions, but I'm a student and we learned VHDL. There's a difference between that and the real world, like timing :) 

 

 

M.
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

Actually a 2.0 ns Setup Relationship corresponds to a 500 MHz clock!  

The WrReq signal is the most elaborate path inside the fifo as it is gated with 'not WrFull' (and probably a few more) to avoid overrun.  

IMHO you should be able to do everything with a single clock (the one you use for the ddio_rxddio_inst block).
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

 

--- Quote Start ---  

Actually a 2.0 ns Setup Relationship corresponds to a 500 MHz clock!  

The WrReq signal is the most elaborate path inside the fifo as it is gated with 'not WrFull' (and probably a few more) to avoid overrun.  

IMHO you should be able to do everything with a single clock (the one you use for the ddio_rxddio_inst block). 

--- Quote End ---  

 

 

Thanks! 

Checked it out and it works perfectly for both RTL and "Fast -M" gate level sim. 

 

ModelSim's "Slow operating modes" are still broken but I guess now is a good time to stop fiddling and put it onto the FPGA for testing. 

 

 

Btw, regarding the "wrreq" signal on the FIFO's. Should they not be put high before the rising edge of the clock - or does the tool automagically take care of that?
0 Kudos
Altera_Forum
Honored Contributor II
4,104 Views

Timequest has verified that wrreq obeys the setup timing. 

Gate Level Simulation can be a bit difficult to interpret because all signals are 'real' and are shifted in time according to the delays in the silicon. Also you have to make sure that the inputs you set in the testbench comply with the required setup and hold times (although modelsim will spit out messages and draw violated signals in 'red'). So putting it on the FPGA and using the scope to verify will be OK.
0 Kudos
Reply