Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20707 Discussions

Multiple Distinct Clocks Error

Altera_Forum
Honored Contributor II
2,417 Views

Hello everyone,  

 

I am trying to write some code to use the debounced keys on the Altera DE2 board. I have spent days on the same error: "Error (10820): Netlist error at lab1.vhd(49): can't infer register for CurAddr[0] because its behavior depends on the edges of multiple distinct clocks"  

 

process(clock, resetn) variable CurAddr : std_logic_vector(3 downto 0); variable CurData : std_logic_vector(7 downto 0); variable output : std_logic_vector(6 downto 0); begin if(clock'EVENT and clock='1') then if(key(3)'EVENT and key(3)='0') then if(conv_integer(CurAddr) = 16) then CurAddr := "0000"; end if; CurAddr := CurAddr + "0001"; elsif(key(2)'EVENT and key(2)='0') then if(conv_integer(CurAddr) = 0) then CurAddr := "1111"; end if; CurAddr := CurAddr - "0001"; elsif(key(1)'EVENT and key(1)='0') then if(CurData = "11111111") then CurData := "00000000"; end if; CurData := CurData + 1; elsif(key(0)'EVENT and key(0)='0') then if(CurData = "00000000") then CurData := "11111111"; end if; CurData := CurData + 1; end if; end if; ram_addr <= CurAddr; --STORE RAM_ADDR data_in <= CurData; -- STORE DATA hex6 <= led_out1; -- OUTPUT LED CODE end process;  

 

I have tried removing the key(#)'EVENT parts. This removes the error but then the Seven Segment Display increments randomly it seems. I am using the 4 keys on the DE2 to control a RAM address and increment or decrement the value in that address. 2 keys to increment/decrement the address and 2 to control the value. I have also tried chaning the variables to signals. This didn't help either. I have also tried changing it to process(key) and removing the 'EVENT part as well as changing key(3)'EVENT to key(3)'last_value='1'. I am having no luck or intelligence. Any suggestions? 

 

Thank you.  

 

V/R,  

Alan
0 Kudos
12 Replies
Altera_Forum
Honored Contributor II
1,030 Views

You are right, you need the tick-event. That line means the clock has changed and it is nowt a '1'. Without the 'event, it just means when the clock is high, update this process, more like a transparent latch. 

 

Take those signal assignments at the end and move them up just enough to be inside the clock edge if statement. This will make them rising edge registers.
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Before experimenting with the VHDL trying to fix it by trial and error: 

 

For logic, think about what you want the hardware to look like in terms of registers versus combinational logic. For the register portion, you will have a D input, clock, asynchronous reset, and possibly other inputs like a clock enable. Write your VHDL in the recommended coding style for registers that have those input signals. For the coding styles, see the Quartus handbook, Volume 1, Section II, Chapter 6. In that chapter, see "Coding Guidelines for Registers and Latches". 

 

For memory, go through a similar process to be clear about what you want for memory control signals like the clock. See "Inferring Memory Functions from HDL Code" in the same handbook chapter.
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Good referrences, and this gives me the forum to push my favorite book for people settling on a coding approach, HDL Chip Design by Doug Smith. He has, for example, all the typical flavors of a Flip Flop written with example code "The way it should be done" for both verilog and VHDL. There are little dialog boxes pointing to and explaining how each variation in the HDL text gives you a slightly different feature. It's not deep, but if you are looking for the right approach to basic synthesizable code, this is the ticket.

0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Thanks for the help. Pushing the signal assignments inside the if(clock'EVENT and clock='1') statement still generated the same error? I will read those links as well.

0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Get rid of the key(3)'EVENT and just use the value of key, as that will get rid of the error. You clk'EVENT already describes the clock for a register, and you can only have one clock for each register. Doug Smith's book should give you some good direction, although opening almost any VHDL file will show you the standard method for doing flops(Doug Smith's book will clarify what is going on). I think I mentioned this before, but I really think understanding schematics is a good way to start coding, even if you're writing VHDL/Verilog. If you're just starting coding, and can't imagine what the code you're writing would look like as a schematic, than you're in trouble. (The original code with multiple 'EVENT lines is a good example, is I don't know how to "draw" that.) 

 

The second thing I would stay away from in VHDL is variables, and try to always use Signals. Signals represent physical nets in the design, and again would map to something in a schematic. I had a long argument with someone who loved Variables about this. He spent a lot of time trying to come up with logic where Variables did a better job than Signals. On all but one, I was able to do the same thing, in a more concise manner, with Signals. But the point is that if you're new to VHDL, it will keep you writing code that physically makes sense, rather than writing algorithms where you have no idea how they get synthesized and what comes out the other side. 

 

Finally, for your design, the fix I mentioned will get it to compile, but probably won't be what you want. If your level-sensitive to key, then if the user holds down the key for more than one clock cycle(and I'd like to meet the person who doesn't do that), then the pointers will keep iterating for many clocks. There are many ways to fix this, depending on how much caution you want to build in. Most likely you want a separate process for each key that is based on key'EVENT, where the register gets the inversion of itself(i.e. a toggle register where key(#) is the clock). THen you need to move that signal into your main clk domain, so have the output of that register feed two registers clocked by clk'EVENT. Take the output of those two registers and feed them into an XOR gate, which will go high whenever the two registers are not equal(i.e. an edge detect). That should be a good starting point. It may not be full-proof enough if your pushbuttons are launch warheads(I don't think we've gotten into metastability, correlation between multiple keys, etc.) but if the failure rate is one out of every trillion key strokes, I'm guessing that's fine for now.
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Thank you for everyone's help. I didn't really understand most of it, but I'll check out those references. Here is the way I finally solved the problem: 

 

if(clock'EVENT and clock='1') then we <= '0'; if(key(3)='1' and key(2)='1' and key(1)='1' and key(0)='1') then EnableKeyPress := '1'; end if; if(key(3)='0' and EnableKeyPress='1') then EnableKeyPress := '0'; if(conv_integer(ram_addr) = 16) then ram_addr <= "0000"; else ram_addr <= ram_addr + "0001"; end if; elsif(key(2)='0' and EnableKeyPress='1') then EnableKeyPress := '0'; if(conv_integer(ram_addr) = 0) then ram_addr <= "1111"; else ram_addr <= ram_addr - "0001"; end if; elsif(key(1)='0' and EnableKeyPress='1') then EnableKeyPress := '0'; we <= '1'; if(data_out = "11111111") then data_in <= "00000000"; else data_in <= data_in + 1; end if; elsif(key(0)='0' and EnableKeyPress='1') then EnableKeyPress := '0'; we <= '1'; if(data_out = "00000000") then data_in <= "11111111"; else data_in <= data_in - 1; end if; end if; end if; 

 

It seems to work. I have a few quarks to work out with the ram, but the button detecting code works. Thanks for all the help. Does anyone see any reason why this code should not be used?
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

I suggested thinking in terms of how you want your logic implemented in physical resources like registers and register control signals. Then Rysc suggested doing that by thinking about how the logic looks in a schematic. Now that you have something you can synthesize, you can look at a post-synthesis schematic that represents what you did do. By comparing post-synthesis schematics to your HDL, you can see how the HDL was translated to physical device resources. This might help you next time to think in advance about how you want your logic to look as a schematic so that you can write the HDL in a style that produces what you want in hardware. 

 

To see a direct correspondence between the HDL and an equivalent schematic representation of the logic as generic registers, muxes, AND gates, etc., use the RTL Viewer. To see the next step of how that logic maps into the device's registers, LUTs, RAM blocks, etc, use the Technology Map Viewer. Both of these schematic viewers are available at Tools --> Netlist Viewers. 

 

Documentation on the schematic viewers is in the Quartus handbook, Volume 1, Section III, Chapter 12: Analyzing Designs with Quartus II Netlist Viewers.
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Thank you. I will check out those references in the lab today after lunch.

0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

"I didn't really understand most of it, but I'll check out those references." 

 

In general, I find that if you do not really understand how something is supposed to work,  

it is next to impossible to get what you want. 

 

Check out the references cited, and take the time to really get it. 

You will be very happy you spent the time up front 'for the rest of your life'.
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

I received the same error about the multiple clocks. My design had the following format: 

 

process (rst, clk) begin if rising_edge(rst) then -- asynchronous reset stuff elsif rising_edge(clk) then -- synchronous stuff end if; end process; 

 

The fix for me was to change my reset from rising edge triggered to level sensitive: 

 

process (rst, clk) begin if (rst = '1') then -- asynchronous reset stuff elsif rising_edge(clk) then -- synchronous stuff end if; end process; 

 

Hope this helps.
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

I have the similar error when I try to compile a code to stretch an input pulse for some clock cycles . 

 

The code compiles and simulates perfectly,except when I add the line "shp_out<=shaped_output"..where I tryto put the signal shaped_output into the port shp_out. 

It gives me an Error (10820):: can't infer register because its behavior depends on the edges of multiple distinct clocks 

 

 

 

 

entity integrate1 is 

port ( 

 

trig : out std_logic; 

trigger_input,clk_pulse: inout STD_LOGIC 

 

 

); 

 

end integrate1; 

 

architecture arc of integrate1 is 

signal shaped_output: std_logic:='0'; 

signal tmp: std_logic_vector(10 downto 0); 

signal shp_out:std_logic; 

 

 

 

 

begin 

 

process (clk_pulse,trigger_input) 

begin 

if (rising_edge(trigger_input)) then 

tmp<="00000000000"; 

shaped_output<='1'; 

end if; 

 

if shaped_output='1' then 

if (tmp="00000000100") then  

tmp <= "00000000000"; 

shaped_output<='0';  

 

 

elsif (clk_pulse'event and clk_pulse='1') then  

tmp <= tmp + 1;  

end if;  

end if;  

end process; 

shp_out<=shaped_output;<<<<<<<<<<----------PROBLEM  

 

end arc;
0 Kudos
Altera_Forum
Honored Contributor II
1,030 Views

Don't use two clocks in the same process. Just read and act on the trigger input inside the "elsif (clk_pulse'event and clk_pulse='1')" part of the process.

0 Kudos
Reply