Reset from Port to internal components connection - vhdl

I have a Module consisting from another module. e.g.
entity Layer is
port (
CLK: IN std_logic; -- Clock
DIN: IN std_logic;
RST: IN std_logic -- Reset
); -- Data
end Layer;
architecture Behavioral Layer is
component MVM
port (
CLK: IN std_logic; -- Clock
DIN: IN std_logic; -- Data
RST: IN std_logic -- Reset
);
end component;
signal MVM_RST: std_logic;
port MAP( DIN => DIN, CLK => CLK, RST => MVM_RST);
process(CLK) is
begin
if rising_edge(CLK) then
IF RST='1' then
MVM_RST <= '1';
ELSE
MVM_RST <= '0';
END IF;
END IF;
END PROCESS;
end Behavioral;
The logic behind this is I have several other modules connected to reset (not shown in this example) and want them to reset at different time steps but all at the beginning
(i dont know if this is runable, because i wrote it only as a minimin example)
my module 'MVM' is something like
IF RST='1' THEN
MVM_RESULT <= '0';
ELSE
MVM_RESULT <= DIN;
END IF;
The In port of the top module (the layer) is getting new data every clock cycle except for the first one. The first clock cycle is reserved for a high impulse of the reset signal. It starts with clock 0 to get a 0->1 transition
When I am looking at my simulation, the module receives data from the 3th cycle (or?). but so I am loosing 2 cycles instead of 1 cycle
The problem behind this is the part
if rising_edge(CLK) then
IF RST='1' then
MVM_RST <= '1';
ELSE
MVM_RST <= '0';
END IF;
As far as I understand, it means in the first cycle MVM_Res is seted to 1 (which is correct), at the second clock cycle is set to 0, this means for me it can receive data from the 3th cycle (or?)
How to avoid the delay of two cycles. I only want a maximum of 1 cycle delay. I also dont want to directly connect my top module-reset to the component-reset
Here is my testbench (I converted the values to std_logic instead std_logic_vectors to have a minimum example)
entity tb_Layer is
end tb_Layer;
architecture TEST of tb_Layer is
component Layer is
port(
CLK,DIN, RST: IN std_logic;
);
end component;
signal CLK, DIN, RST: std_logic;
BEGIN
uut: Layer PORT MAP(
CLK=> CLK, DIN => DIN, RST=> RST);
tb: process
BEGIN
CLK <= '0';
RST <= '1';
DIN <= '0';
wait for 100ns;
CLK <= '1';
wait for 100ns;
RST <= '0';
CLK <= '0';
DIN <= '1';
wait for 100ns;
CLK <= '1';
wait for 100ns;
CLK <= '0';
DIN <= '0';
wait for 100ns;
CLK <= '1';
wait for 100ns;
END PROCESS;
end TEST;
What the component sees:
The problem is that the first edge it transmits the RST high. SO the component sees after half a cycle too late the Reset high. But because of this the component sees a half cycle the 'u' and so the issue occurs.

You still have the same reason as in your other question, the synchronous reset. In that question, you left the stimulating signals undefined in the first clock cycle, and wondered why the result occurred one clock cycle later than you expected. The suggested change removed the first problem, but not your current issue.
BTW, the shown wave diagram does not match the code of the test bench. Therefore, I respond to the wave diagram, because it seems that this is you problem.
Again, the synchronous nature of the internally generated reset signal delays the reset of the component MVM by one cycle:
At the first rising edge of CLK the signal MVM_RST latches the 'U', as this is the value of RST.
At the second rising edge of CLK the signal MVM_RST latches the '1' of RST and resets MVM_RESULT to all zeroes.
At the third rising edge of CLK the signal MVM_RST latches the '0' of RST and let MVM_RESULT take the value of DIN.
If you had evaluated and simulated the shown test bench, it would go like this:
At the first rising edge of CLK the signal MVM_RST latches the '1' of RST and resets MVM_RESULT to all zeroes.
At the second rising edge of CLK the signal MVM_RST latches the '0' of RST and let MVM_RESULT take the value of DIN.
You might want to learn how to display waves of internal signals with your simulator. Then you can look at MVM_RST to see when it is active.

Related

ISIM signal assignment delay

I expected signal 'delay' to be one clock cycle late wrt to the entities' port 'input', but ISIM shows no phase shift.
I thought there is always is a delay between signal assignment and actual value (when the process suspends), but I don't seee it here.
Why is this?
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test is
Port ( clk: in std_logic;
input: in std_logic
);
end test;
architecture Behavioral of test is
signal delay: std_logic:= '0';
begin
proc1: process(clk)
begin
if(rising_edge(clk)) then
delay <= input; -- ISIM shows no delay between them
end if;
end process;
end Behavioral;
Testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY tb_testbench_test IS
END tb_testbench_test;
ARCHITECTURE behavior OF tb_testbench_test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT test
PORT(
clk: in std_logic;
input: in std_logic
);
END COMPONENT;
--Inputs
signal clk: std_logic := '0';
signal input: std_logic := '0';
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: test PORT MAP (
clk => clk,
input => input
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for clk_period * 9.5;
input <= '1';
wait for clk_period;
input <= '0';
wait;
end process;
end;
Your test bench describes clk and input going high at the same time. You then have a process in your entity that is looking for a rising_edge of clk. Therefore, when your process runs, and asks 'was there a rising edge of the clock?', if the answer to this is 'yes', i.e. the clock signal had just become '1', then the state of the input must also be '1', because the two signals changed at the same time. The delay signal then takes this new input, giving the result you see.
A more realistic scenario would be a change of the input being caused by a rising edge of clk. You can easily simulate this by modifying your stimulus process:
stim_proc: process
begin
wait for clk_period * 9.5;
wait until clk = '1'; -- Sit here until we have seen a rising edge of `clk`
input <= '1'; -- This assignment now happens *after* the clock edge
wait until clk = '1';
input <= '0';
wait;
end process;
The delay between a signal assignment and the appearance of its value is ... one delta cycle. And the time taken by one delta cycle is 0 fS.
What your testbench represents is a race condition whereby you present the input signal and the clock signal at exactly the same time - i.e. in the same delta cycle.
In real hardware, what would happen would be a coin-toss whether the input was seen by this clock edge or the next, or would be some intermediate value when the clock edge happened, raising the possibility of metastable operation.
The simulation has accidentally alerted you to the possibility of such mis-operation.
If you delay the data signal by even one delta cycle (as is guaranteed to happen if it was the output from a previous clocked process) such as a concurrent signal assignment outside the process, you will eliminate the timing hazard and see the delay you expect.

VHDL - FSM not starting (JUST in timing simulation)

I'm working for my master thesis and I'm pretty new to VHDL, but still I have to implement some complex things. This is one of the easiest structures I had to write, and still I'm encountering some problems.
It's a FSM implementing a 24bit shift register with an active-low sync signal (to program a DAC). It's just the end of a complex elaboration chain I created for my project. I followed the example model of a FSM as much as I could.
The behavioral simulation works fine, actually the whole elaboration chain I created works perfectly fine as far as the behavioral simulation concerns. However, once I try the Post-translate simulation things start to go wrong: lots of 'X' output signals.
With this simple shift register I DON'T get any 'X', however I can't get to the load_and_prepare_data phase. It seems that the current_state changes (by inspecting some signals), but the elaboration doesn't go on.
Please keep in mind that since I'm new to the language, I have no idea of what timing constraints I should set on this FSM (and I wouldn't know how to write them on the top.ucf anyway)
Can you see what's wrong?
Thanks in advance
EDIT
I followed your advices and cleaned up the FSM by using a single state process. I still have some doubts about "where to put what" but I really like the new implementation. Anyway I now get a clean behavioral simulation but 'X' on all outputs in post translate simulation.
What is causing this?
I'll post the both the new code and the testbench:
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:44:03 11/28/2014
-- Design Name:
-- Module Name: dac_ad5764r_24bit_sr_programmer_v2 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description: This is a PISO shift register that gets a 24bit parallel input word.
-- It outputs the 24bit input word starting from the MSB and enables
-- an active low ChipSelect line for 24 clock periods.
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity dac_ad5764r_24bit_sr_programmer_v2 is
Port ( clk : in STD_LOGIC;
start : in STD_LOGIC;
reset : in STD_LOGIC; -- Note that this reset is for the FSM not for the DAC
reset_all_dac : in STD_LOGIC;
data_in : in STD_LOGIC_VECTOR (23 downto 0);
serial_data_out : out STD_LOGIC;
sync_out : out STD_LOGIC; -- This is a chip select
reset_out : out STD_LOGIC;
busy : out STD_LOGIC
);
end dac_ad5764r_24bit_sr_programmer_v2;
architecture Behavioral of dac_ad5764r_24bit_sr_programmer_v2 is
-- Stati
type state_type is (idle, load_and_prepare_data, transmission);
--ATTRIBUTE ENUM_ENCODING : STRING;
--ATTRIBUTE ENUM_ENCODING OF state_type: TYPE IS "001 010 100";
signal state: state_type := idle;
--signal next_state: state_type := idle;
-- Clock counter
--signal clk_counter_enable : STD_LOGIC := '0';
signal clk_counter : unsigned(4 downto 0) := (others => '0');
-- Shift register
signal stored_data: STD_LOGIC_VECTOR (23 downto 0) := (others => '0');
begin
FSM_single_process: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
serial_data_out <= '0';
sync_out <= '1';
reset_out <= '1';
busy <= '0';
state <= idle;
else
-- Default
serial_data_out <= '0';
sync_out <= '1';
reset_out <= '1';
busy <= '0';
case (state) is
when transmission =>
serial_data_out <= stored_data(23);
sync_out <= '0';
busy <= '1';
clk_counter <= clk_counter + 1;
stored_data <= stored_data(22 downto 0) & "0";
state <= transmission;
if (clk_counter = 23) then
state <= idle;
end if;
when others => -- Idle
if start = '1' then
serial_data_out <= data_in(23);
sync_out <= '0';
reset_out <= '1';
busy <= '1';
stored_data <= data_in;
clk_counter <= "00001";
state <= transmission;
end if;
end case;
-- if (reset_all_dac = '1') then
-- reset_out <= '0';
-- end if;
end if;
end if;
end process;
end;
And the testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY dac_ad5764r_24bit_sr_programmer_tb IS
END dac_ad5764r_24bit_sr_programmer_tb;
ARCHITECTURE behavior OF dac_ad5764r_24bit_sr_programmer_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT dac_ad5764r_24bit_sr_programmer_v2
PORT(
clk : IN std_logic;
start : IN std_logic;
reset : IN std_logic;
data_in : IN std_logic_vector(23 downto 0);
serial_data_out : OUT std_logic;
reset_all_dac : IN std_logic;
sync_out : OUT std_logic;
reset_out : OUT std_logic;
--finish : OUT std_logic;
busy : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal start : std_logic := '0';
signal reset : std_logic := '0';
signal data_in : std_logic_vector(23 downto 0) := (others => '0');
signal reset_all_dac : std_logic := '0';
--Outputs
signal serial_data_out : std_logic;
signal sync_out : std_logic;
signal reset_out : std_logic;
--signal finish : std_logic;
signal busy : std_logic;
-- Clock period definitions
constant clk_period : time := 100 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: dac_ad5764r_24bit_sr_programmer_v2 PORT MAP (
clk => clk,
start => start,
reset => reset,
data_in => data_in,
reset_all_dac => reset_all_dac,
serial_data_out => serial_data_out,
sync_out => sync_out,
reset_out => reset_out,
--finish => finish,
busy => busy
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for clk_period*10;
reset <= '1' after 25 ns;
wait for clk_period*1;
reset <= '0' after 25 ns;
wait for clk_period*3;
reset_all_dac <= '1' after 25 ns;
wait for clk_period*1;
reset_all_dac <= '0' after 25 ns;
wait for clk_period*5;
data_in <= "111111111111111111111111" after 25 ns;
wait for clk_period*3;
start <= '1' after 25 ns;
wait for clk_period*1;
start <= '0' after 25 ns;
wait;
end process;
END;
UPDATE 1
Updated with the last design: this code is not causing any 'X' (can't figure out why, this doesn't but the previous did). However it's not starting (in POST-TRANSLATE simulation) just like the first 3 process machine, and the signal sync_out is stuck at 0 while it should be '1' by default.
UPDATE 2
I've been looking into the tecnology schematic, starting from the problem of the sync_out=0: it's implemented with a FDS, S is the FSM reset signal, D is coming from a LUT3 with I = state&reset&start and INIT = 45 = "00101101". I've looked for this LUT3 in the simulation and I've noticed that it has INIT = "00000000"!
Is there something I'm missing about how to run this simulation? It seems that every LUT in the design have not been set!
UPDATE 3
It seems that the Post-Translate simulation is buggy in some way, or I'm not configuring it correctly for some reason: the Post-Map and the Post-PAR simulations work and display some outputs.
However there is an odd bug: the stored_data register is not updated with the complete data_in vector, after that, the FSM operates correctly and outputs the data stored.
I've looked in the tecnology schematic just after synthesis and for some reason the bits 23,22,21,19,18 are not connected to the corresponding data_in bit. You can see the effect in this screenshot from Post-Map simulation. Same happens in Post-PAR, but it seems that this problems comes directly from the synthesis!
Solved: the strange output comes from the Synthesis optimization. The tool realized that the previous block in the elaboration chain will never output a bit different from 0 for those specific bit. My mistake was assuming that I could test the single block alone: what I was really testing was the block synthetized for the FPGA taking into account everything else in the design!
Thanks to everybody helped me, I'm going to follow your advices!
I prefer the single-process form of state machine, which is cleaner, simpler and much less prone to bugs like sensitivity-list errors. I would also endorse the points in Paebbels' excellent answer. However I don't think any of these are the problem here.
One thing to be aware of in post-synth and post-PAR simulations is that their model of time is different from the behavioural model. The behavioural model follows simple rules as I described in this answer and ensures that in a typical design flow you can go straight to hardware - without post-synth simulation, without worry.
Indeed I only use post-synth or post-PAR simulations if I'm chasing a suspected tool bug. (For FPGA designs, not ASIC, that is!)
However, that simple timing model has its limitations. You may be familiar with problems like a clock signal assigned via signal assignment (usually buried in a 3rd party model where you don't expect it) which consumes a delta cycle, and ensures that your clocked data arrives before your clock instead of after, and everything subsequently occurs one cycle earlier than intended...
In behavioural modelling, a little discipline will keep clear of such troubles. But the same is not true of post-PAR modelling.
Your testbench is probably set up the same way as the behavioural model. And if so, that is likely to be the problem.
Here's what I do in this situation : I claim no formal authority for it, just experience. It also works well when interfacing the FPGA to external memory models with realistic timings.
1) I assume the simple (behavioural) timing model works correctly for all signals INTERNAL to the design.
2) I assume nothing of the sort for inputs and outputs from the design.
3) I take note of the estimated setup and hold timings on the inputs, (a) from the FPGA datasheet or better, (b) from the worst case values shown in the post-synth or post-PAR report, and structure the testbench around them.
Worked example : setup time 1 ns, hold time 2 ns, clock period 10 ns. This means that any input between 2 ns and 9 ns after a clock edge is guaranteed to be corrrectly read. I choose (arbitrarily) 5 ns.
signal_to_fpga <= driving_value after 5 ns;
(Note that Xilinx makes this absurdly counter-intuitive by expressing them as "offset in/out before/after" which refers timings to a previous or future clock edge instead of the one you're looking at)
Alternatively, if the input is fed from a CPU or memory in the real world, I use datasheet timing specifications for that device.
4) I take note of the worst case clk-out timing reported in the datasheet or report, and structure the design around them. (say, 7 ns)
fpga_output_pin <= driving_value after 7 ns;
Note that this "after" clause is obviously ignored by synthesis; however the post-synth back-annotation will introduce something very like it.
5) If this turns out to be not good enough, then (possibly in a wrapper component to avoid polluting the synthesisable code) improve accuracy like
fpga_output_pin <= 'X' after 1 ps, driving_value after 7 ns;
6) I re-run the behavioural simulation. Typically, it now fails, because it was written without realistic timings in mind.
7) I fix those failures. This may include adding realistic delays before testing values output from the design. It can be an iterative process.
Now, I have a reasonable expectation that the post-PAR simulation model will drop straight in to the testbench and work.
Here are some hints to improve your code:
You can remove the Xilinx dependencies to UNISIM, because you are not using any Xilinx Primitves.
Applying attribute ENUM_ENCODING has no effect on state encoding unless you also define the attribute FSM_ENCODING and set it's value to user. One-Hot encoding can be forced by setting FSM_ENCODING to one-hot. Normally synthesis is smart enough to find the best encoding.
read more ...
None of your registers has a default value:
signal current_state : state_type := idle;
Your FSM is no FSM in the eyes of Xilinx synthesis tool (XST). I'm sure if you look into your synthesis report, you won't find that XST reports a FSM for current_state.
So what's wrong with your FSM?
Your FSM has no initial state.
Your FSM has multiple reset states (idle, load_and_prepare_data)
Your FSM has no transition from idle to load_and_prepare_data (reset is no transition)
Writing next_state transitions for the current state can cause XST to think it's no FSM
the default assignment next_state <= current_state; is sufficient.
If you change the type of signal clk_counter to unsigned you can do arithmetic much easier.
increment: clk_counter <= clk_counter + 1;
clear: clk_counter <= (others => '0');
compare: if (clk_counter = 23) then
It's no good style to use the FSM's state signal outside of the FSM processes.
FSM_next_state_process: process(current_state, start, clk_counter, reset_all_dac)
begin
next_state <= current_state;
OutReg_busy <= '1';
OutReg_reset_out <= '1';
OutReg_sync_out <= '1';
clk_counter_enable <= '0';
case (current_state) is
when idle =>
OutReg_busy <= '0';
if (reset_all_dac = '1') then
OutReg_reset_out <= '0';
end if;
when load_and_prepare_data =>
next_state <= transmission;
when transmission =>
clk_counter_enable <= '1';
OutReg_sync_out <= '0';
if (clk_counter = 23) then
next_state <= idle;
end if;
when others =>
next_state <= idle;
end case ;
end process;

Signal led cannot be synthesized, bad synchronous description?

I have created a frequency divider, and I want to test it using a FPGA board. To test it I want to make a led flicker with the divided frequency, if a switch is on. The problem is that I do't know how to change the value of the led if clock is not on rising edge.
Here is the exact error I get:
line 51: Signal led cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
-->
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity divizor1 is
Port (clk : in STD_LOGIC;
--clk_out : out STD_LOGIC;
btn : in STD_LOGIC;
led : out STD_LOGIC
);
end entity divizor1;
architecture divizor_frecv of divizor1 is
signal cnt : std_logic_vector (24 downto 0);
signal clock :std_logic;
signal bec : std_logic;
begin
process(clk)
begin
if rising_edge(clk) then
cnt<=cnt +1;
end if;
if (cnt = "1111111111111111111111111") then
--clk_out <= '1';
clock <= '1';
else
-- clk_out <= '0';
clock <= '0';
end if;
end process;
process (clock, btn)
begin
if btn = '1' then
if clock'event and clock = '1' then
led <= '1';
else
led <= '0';
end if;
end if;
end process;
end divizor_frecv;
The error message appears to be complaining that you are using the output of the cnt counter as a clock.
Instead you could use it as a toggle enable and clk as the clock:
--process (clock, btn)
process (clk, btn)
begin
-- if btn = '0' then
if btn = '1' then -- reset led
led <= '0'; -- or '1' which ever turns it off
-- if clock'event and clock = '1' then
elsif clock = '1' and rising_edge(clk) then -- clock as enable
-- led <= '1';
led <= not led;
-- else
-- led <= '0';
end if;
-- end if;
end process;
The state of btn made a convenient reset to provide an initial value for led to be able to use not led. This either requires the port signal led be made mode inout or you need a proxy variable or signal which is assigned to led so the not led works (so led can be read). A default value for cnt would also help simulation.
I cheated and made your counter cnt shorter and set the clock to 4 MHz to illustrate:
The simulation was done using ghdl and gtkwave.
process (clock, btn)
begin
if btn = '1' then
if clock'event and clock = '1' then
led <= '1';
else
led <= '0';
end if;
end if;
end process;
At a first glance, I would have guessed the button was a clock enable here. However, the else part is connected to the clock. So you've asked for led to go high at the rising clock edge and low at all other times; given that the clock edge is an instant, this doesn't make much sense (it would always be low). I expect you want to update led based on some other state on the clock edge, for instance:
process (clock)
begin
if clock'event and clock = '1' then
led <= btn;
end if;
end process;
If all you wanted was for the LED to indicate the clock pulses (which may well be too fast to detect) you could just route clock directly to led. Your divider is already producing very short pulses (usually we aim for 50% duty cycle, this has 0.000003%).

delay in VHDL register

I have simple register which stores value as std_logic_vector. In simulation behavior, the output is delayed by 1 cycle. What is the reason behind that? Is it behavior due to clock'event? How to solve this issue?
Here is the code:
entity fault_reg is
port (
clk : in std_logic;
rst : in std_logic;
reg_in : in std_logic_vector(NUM_PORTS - 1 downto 0);
reg_out : out std_logic_vector(NUM_PORTS - 1 downto 0));
end fault_reg;
architecture Behavioral of fault_reg is
begin
reg_impl : process(clk, rst)
begin
if rst = '1' then
reg_out <= (others => '0');
elsif clk'event and clk='1' then
reg_out <= reg_in;
end if;
end process reg_impl;
end Behavioral;
Here is the waveform:
The process you written is a synchronous process, which is sensitive to the clk and rst signals; the process only "wakes up" to evaluate/update outputs when clk or rst changes. So even though reg_in may change, reg_out will only update on the next rising clock edge (clk'event and clk='1') or reset is asserted (rst = '1').
The timeline breaks down like this:
Rising clock edge.
reg_in changes soon after event #1.
Rising clock edge.
reg_out changes soon after event #3, with the value of reg_in that was present at event #3, which was the value that it changed to in event #2.

Flip-Flop triggered on the edge of two signals

I need a flip flop that reacts on the edges of two different signals. Something like this:
if(rising_edge(sig1)) then
bit <= '0';
elsif(rising_edge(sig2)) then
bit <= '1';
end if;
Does such a flip flop exist or is there some other technique i could use?
I need this to be synthesizable on a Xilinx Virtex-5 FPGA.
Thanks
What I'd usually do in this case is to keep a delayed version of both the control signals and generate a pulse one clock wide at the rising edge of each signal. I'd then use these pulses to drive a tiny FSM to generate the 'bit' signal. Here's some VHDL below.
-- -*-vhdl-*-
-- Finding edges of control signals and using the
-- edges to control the state of an output variable
--
library ieee;
use ieee.std_logic_1164.all;
entity stackoverflow_edges is
port ( clk : in std_ulogic;
rst : in std_ulogic;
sig1 : in std_ulogic;
sig2 : in std_ulogic;
bito : out std_ulogic );
end entity stackoverflow_edges;
architecture rtl of stackoverflow_edges is
signal sig1_d1 , sig2_d1 : std_ulogic;
signal sig1_rise, sig2_rise : std_ulogic;
begin
-- Flops to store a delayed version of the control signals
-- If the contorl signals are not synchronous with clk,
-- consider using a bank of 2 delays and using those outputs
-- to generate the edge flags
delay_regs: process ( clk ) is
begin
if rising_edge(clk) then
if rst = '1' then
sig1_d1 <= '0';
sig2_d1 <= '0';
else
sig1_d1 <= sig1;
sig2_d1 <= sig2;
end if;
end if;
end process delay_regs;
-- Edge flags
edge_flags: process (sig1, sig1_d1, sig2, sig2_d1) is
begin
sig1_rise <= sig1 and not sig1_d1;
sig2_rise <= sig2 and not sig2_d1;
end process edge_flags;
-- Output control bit
output_ctrl: process (clk) is
begin
if rst = '1' then
bito <= '0';
elsif sig1_rise = '1' then
bito <= '1';
elsif sig2_rise = '1' then
bito <= '0';
end if;
end process output_ctrl;
end rtl;
I'm a lot more comfortable in verilog, so double check this VHDL (any comments appreciated).
waveforms http://img33.imageshack.us/img33/893/stackoverflowvhdlq.png
This code assumes that the clock is fast enough to capture all the control signal pulses. If the control signals are not synchronous with the clock, I'd keep a further delayed version of the delayed control signal (eg sig_d2) then make the flags from sig_d1 and sig_d2.

Resources