- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
9 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 :)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page