Forum Discussion
Multiple Distinct Clocks Error
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, Alan12 Replies
- Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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.
- Altera_Forum
Honored Contributor
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.
- Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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:
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?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; - Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
Thank you. I will check out those references in the lab today after lunch.
- Altera_Forum
Honored Contributor
"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'. - Altera_Forum
Honored Contributor
I received the same error about the multiple clocks. My design had the following format:
The fix for me was to change my reset from rising edge triggered to level sensitive:process (rst, clk) begin if rising_edge(rst) then -- asynchronous reset stuff elsif rising_edge(clk) then -- synchronous stuff end if; end process;
Hope this helps.process (rst, clk) begin if (rst = '1') then -- asynchronous reset stuff elsif rising_edge(clk) then -- synchronous stuff end if; end process;