问题
I'm pretty new to VHDL (and digital circuits in general), and I'm trying to implement a counter of two digits using BCD style blocks. External to this circuit there is going to be buttons, which when pressed, will bump the digit of interest up by one (much like an alarm clock would). This is an asynchronous action, and will occur when in some form of edit mode (externally enforced). The code I have written works fine without the "elsif rising_edge(digitUp1) then" and "elsif rising_edge(digitUp1) then" blocks, but fails with them included. I really have no idea why it doesn't work or how I can fix it. Keep getting errors like "couldn't implement registers for assignments on this clock edge", "can't infer register for count2[3] because its behavior depends on the edges of multiple distinct clocks" and "Can't infer register for "count2[3]" at MinuteCounter.vhd(21) because it does not hold its value outside the clock edge". Any help would be greatly appreciated.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
-- ToDo: ENFORCE ON ALL COUNTERS (externally) LOGIC TO PAUSE AT MAX/MIN
entity MinuteCounter is
port( clockIn, digitUp1, digitUp2, reset, counting, countUp : in std_logic;
clockOut : out std_logic;
BCD1, BCD2 : out std_logic_vector(3 downto 0));
end MinuteCounter;
architecture structure of MinuteCounter is
signal count1, count2 : std_logic_vector(3 downto 0);
signal carryOut : std_logic;
begin
process( clockIn, digitUp1, digitUp2, countUp, reset, counting)
begin
-- Asynchronous reset
if reset = '1' then
count1 <= "0000";
count2 <= "0000";
-- What to run when there's an active edge of the clock
elsif rising_edge(clockIn) then
-- Code to run when timer is running
if counting = '1' then
-- What to do when counting up
if countUp = '1' then
if ((count1 = "1001") and (count2 = "0101")) then
count1 <= "0000";
count2 <= "0000";
if carryOut = '0' then
carryOut <= '1';
else
carryOut <= '0';
end if;
elsif count1 = "1001" then
count1 <= "0000";
count2 <= count2 + 1;
else
count1 <= count1 + 1;
end if;
-- What to do when counting down (This logic is hard to understand)
else
if ((count1 = "0000") and (count2 = "0000")) then
count1 <= "1001";
count2 <= "0101";
if carryOut = '0' then
carryOut <= '1';
else
carryOut <= '0';
end if;
elsif count1 = "0000" then
count1 <= "1001";
count2 <= count2 - 1;
else
count1 <= count1 - 1;
end if;
end if;
-- When counting is disabled, but there is an active edge (do nothing)
else
count1 <= count1;
count2 <= count2;
end if;
-- Code to run when entering values (will not be run if counting = '1') << Externally enforced
elsif rising_edge(digitUp1) then
if count1 = "1001" then
count1 <= "0000";
count1 <= count1 + 1;
else
count1 <= count1 + 1;
end if;
-- Code to run when entering values (will not be run if counting = '1') << Externally enforced
elsif rising_edge(digitUp2) then
if count2 = "0101" then
count2 <= "0000";
count2 <= count2 + 1;
else
count2 <= count2 + 1;
end if;
-- What to do when there is no active edge or other events (nothing)
else
count1 <= count1;
count2 <= count2;
end if;
end process;
-- Assign outputs
BCD1 <= count1;
BCD2 <= count2;
clockOut <= carryOut;
end structure;
回答1:
The "why it doesn't work" is explained in the question title : Multiple rising_edge detections inside a process block.
VHDL is designed to describe hardware, and there is no basic circuit element that responds to multiple clock signals. So you cannot describe a circuit that way.
So how do you fix it?
You transform the circuit into one where any single process only has one clock signal (and optionally, one asynchronous reset signal as you are using correctly). This can be implemented using real registers and flip flops.
Two ways are :
- several processes, using signals to communicate between them
- A single process, with a single clock, sampling the other signals on the main clock edge.
The correct decision between these requires some overall knowledge of the design.
Here it sounds as if all three clock signals are actually button presses, rather than one fast clock. Therefore you cannot guarantee that there will be a clock edge while another button is pressed.
So here is one of many ways forward : make a clock signal (outside the process) which will cover all three input events.
my_clock <= clockIn or digitUp1 or digitUp2;
Now you can rewrite the process using this clock:
process(my_clock, reset) is
begin
if reset = '1' then
-- reset actions
elsif rising_edge(my_clock) then
-- what caused this event?
if digitUp1 = '1' then -- bump digit 1
elsif digitup2 = '1' then -- bump digit 2
else -- count normally
endif;
end if;
end process;
Notes:
- As this is a proper synchronous process, only clock and reset belong in the sensitivity list.
- Though this will work in a sense, it may not be what the customer wants : what happens if he holds down all three buttons for example? You may want to explore other approaches to the design.
来源:https://stackoverflow.com/questions/19879960/vhdl-multiple-rising-edge-detections-inside-a-process-block