Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Initial value depending on the input

Status
Not open for further replies.

bremenpl

Member level 3
Joined
Jan 5, 2013
Messages
63
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,827
Hello there,
I am designing a simple debounce mechanism in VHDL. I have the following problem. An internal counter (a variable) should be initially set to 0 or some value (ie. 100), depending on either the input is high or low at power up. I have no idea how to implement this. Is it even possible? At the moment my internal "key" state is initialized with input value, but for some reason this doesnt work. The first transition always fails (no debounce). I am using additional boolean generic's in order to enable the debounce for either up or low transitions.

Code:
-- Libraries -------------------------------------------------------------------

--! Main library
library ieee;				
	--! std logic components		
	use ieee.std_logic_1164.all;

-- Entity ----------------------------------------------------------------------

--! bouncer signals
entity entity_debounce is
	generic
	(
		--! Stores the maximum hysteresis value. 
		max				: 	natural;
		
		--! Disables the up counting hysteresis when true
		hystup_dis		:	boolean;
		
		--! Disables the down counting hysteresis when true
		hystdown_dis	:	boolean
	);

	port 
	( 	
		--! Clock signal. Rising edge triggers the counter.
		clk 	: in 	std_logic;	
		
		--! Input signal that needs debouncing
		input 	: in 	std_logic;	
		
		--! clean, debounced output
		output	: out 	std_logic 	
	);

end entity_debounce;

-- Architecture ----------------------------------------------------------------

--! Debounce hysteresis mechanism implementation
architecture arch_debounce of entity_debounce is

	--! internal key memory state
	signal key		: std_logic := input;	
	
begin
	
	process_debounce : process(clk)
		
		--! Hysteresis counter
		variable cnt : natural := 0;
		
		begin
			if (rising_edge(clk)) then
				if (input = '1') then
					if ((cnt < max) and (hystup_dis = false)) then
						cnt := cnt + 1;
					elsif (key = '0') then
						key <= '1';
						cnt := max;
					end if;
				else 
					if ((cnt > 0) and (hystdown_dis = false)) then
						cnt := cnt - 1;
					elsif (key = '1') then
						key <= '0';
						cnt := 0;
					end if;
				end if;
			end if;
	end process;
	
	output <= key;

end arch_debounce;

.
.
.

In the top vhd file:

Code:
	--! Debouncer instance 20 ms hysteresis debounce time
	debounce_ledbtn20ms : entity_debounce
		generic map 
		(
			max => 656,
			hystup_dis => true,
			hystdown_dis => false
		)
	
		port map
		(
			clk => clk_32k,
			input => pin_ledbtn,
			output => pins_led(0)
		);

On the scope one can see that 1st transition is not correct, since falling edge should have debounce added (hystdown_dis => false). There should never be debounce added on rising edges and that is OK (hystup_dis => true).

bounce.png


I would appreciate all help.
 
Last edited:

An initial value is either synthesized as constant or power-on-reset value, depending on the logic, in your case the latter.

POR value can't depend on input, instead you'll need an explicit reset that stores the initial value. Simple, straightforward.

You should consider that some logic families don't support asynchronous set function and need to emulate it by a logic loop latch, e.g. all newer Intel FPGA. As a drawback, the POR value of this latch will be undetermined.
 

Hello, thank you for answer.

you'll need an explicit reset that stores the initial value. Simple, straightforward.

I tried doing just that- it did not help as well. I think in my situation (MachXO2 from Lattice) it is somewhat not possible to initialize the values this way. For example, when I created a separate bolean variable that is initialy false, and then in the behavioral code I check either it is false and set it to true forever, the synthesizer gave me a warning that my variable will always be true. So, its like it was never initialized with false. Also, the code didnt work so this had to be the case...
 

You didn't show what you have tried. As said, the posted code, using an input value as initializer doesn't work.

Reading an input during reset and initializing a counter respectively should work. I have coded similar hardware more than once.
 

You didn't show what you have tried. As said, the posted code, using an input value as initializer doesn't work.

Reading an input during reset and initializing a counter respectively should work. I have coded similar hardware more than once.

You are right, but the thing is to make the input being read only once. Please take a look at this MWE:

Code:
--! Debounce hysteresis mechanism implementation
architecture arch_debounce of entity_debounce is
	
begin
	
	process_debounce : process(clk)
		
		variable test : bolean := false;
		
		begin
		
		if (test = false)
			test = true; -- this code is never run
		end if;
			
	end process;

The problem lies in the test variable. The if statement was designed to run some portion of code only once per whole device reset. Why doesnt it work?
 

Yes the code synthesis to nothing for two reasons:
- nothing depends on the test signal
- it's rewritten in combinational code

Need to synthesize a register, in other words assign the new value on clock event.
 

This is just an example. In the if statement part I had another statement that sets the counter variable, depending on the input signal. That did not work as well. How else can I create a 1 time execution situation?
 

Basically something like below. A reset synchronizer may be required to assure consistent action of the first clock edge.

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
process (reset, clk)
begin
  if reset = '1' then
    init_done <= '0';
  elsif rising_edge(clk) then
    if init_done = '0' then
      init_done <= '1';
      init_reg <= init_inp;
    end if;
  end if;
end process;

 

I see... But the problem here is that the mentioned reset signal is probably a signal entering the component. This design would require a physical reset to be performed a startup, this is not automatic, do I understand correctly?
 

Hi,

I'm not sure wheter I understand the problem correctly.

I assume you have one input and one output...and at powerup you want the output to have the same logic state as the input, but as soon as possible.
The dilemma is, that the usual timing is:
* Power up (FPGA signals are not initiated yet, thus high impedance)
* time to load the FPGA configuration (FPGA signals are not initiated yet, thus high impedance)
* FPGA is initiated and thus the output only can be configured as fix HIGH, LOW or Z (but you don't want fix H or L here)
* FPGA is operating and now can react an output a signal depending on an input (but now it's too late for your idea)

If my assumptions above are correct, then the only solution I see is to use an external resistor between input and output.
This makes the "output" to get the same state as the "input" as long as the "output" is in Z state.
As soon as you switch the "output" to H or L the FPGA controls the state (overriding the resistor)

Klaus
 

External hardware reset is the preferred method and should be always provided in a good design. Problems arise particularly, if the input clock is already present when the internal power on reset is released.

It's nevertheless possible to generate an internal reset, although it can't be guaranteed to be completely free of metastable events.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
SIGNAL reset_int           : STD_LOGIC := '1';
   SIGNAL reset_cnt           : INTEGER RANGE 0 TO 7 := 0;
   PROCESS (clk)
   BEGIN
      IF rising_edge(clk) THEN
         IF reset_cnt = 7 THEN
            reset_int <= '0';
         ELSE
            reset_cnt <= reset_cnt + 1;
         END IF;
      END IF;
   END PROCESS;



- - - Updated - - -

I'm not sure whether I understand the problem correctly.
I understand that he wants to perform a specific action (set a register according to input signal) once after the POR has been released.

Obviously, the FPGA IOs are already configured at this time.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top