0

For practice, I attempted to make a VHDL code to run Rotary encoder hardware. It was full with debounce, quadrature decoder and an up/down counter codes.

Unfortunately, when running simulation with a testbench, my results were disappointing so I decided that each block needs to be analysed separately. For the debounce code, I created a symbol file and produced the circuit below

schematic setup for simulating the debounce block (clickable)

While attempting to debounce the testbench signal in simulation, I found out that my results were terrible so I believe I am missing something.

modelsim simulation using debounce testbench values (clickable)

The VHDL code for the encoder block can be found here :

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY debounce_a IS
GENERIC( counter_size  :  INTEGER := 8); --counter size (8 bits gives 51.6 us with 5MHz clock)
PORT(
clk     : IN  STD_LOGIC;  --input clock
bounce_a  : IN  STD_LOGIC;  --input signal to be debounced
result  : OUT STD_LOGIC); --debounced signal
END debounce_a;

ARCHITECTURE logic OF debounce_a IS
SIGNAL flipflops   : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
SIGNAL counter_set : STD_LOGIC;                    --sync reset to zero
SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
BEGIN

counter_set <= flipflops(0) xor flipflops(1);   --determine when to start/reset counter

PROCESS(clk) -- occurs within a clock event
BEGIN
IF(clk'EVENT and clk = '1') THEN -- can be rising_edge(clk)
flipflops(0) <= bounce_a;                   -- adresses the signal as a set value
  flipflops(1) <= flipflops(0);
  If(counter_set = '1') THEN                  --reset counter because input is changing
    counter_out <= (OTHERS => '0');           --set all bits to '0'
  ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
    counter_out <= counter_out + 1;
  ELSE                                        --stable input time is met
    result <= flipflops(1);
  END IF;    
END IF;
END PROCESS;
END logic;

It could be filled to the brim with unwanted logic because I had a limited idea of what I was doing and I took a friends general debounce code and edited it to try and fit my specific needs.

If anything extra is needed I am willing to provide. I feel like it's a pretty basic error but I just need any sort of help.

Here is a look on the testbench code that I used if that helps identify toggling properties :

   LIBRARY ieee;                                               
   USE ieee.std_logic_1164.all;                                

   ENTITY decodeblock_vhd_tst IS
   END decodeblock_vhd_tst;
   ARCHITECTURE decodeblock_arch OF decodeblock_vhd_tst IS
   -- constants   
   CONSTANT clk_period : TIME := 20 ns;
   CONSTANT num_clk_cycles : INTEGER := 100;                                              
   -- signals                                                   
     SIGNAL b_Input : STD_LOGIC;
     SIGNAL b_output : STD_LOGIC;
     SIGNAL CLOCK_50 : STD_LOGIC := '0'; 
     COMPONENT decodeblock
 PORT (
 b_Input : IN STD_LOGIC;
 b_output : OUT STD_LOGIC;
 CLOCK_50 : IN STD_LOGIC
 );
     END COMPONENT;
     BEGIN
i1 : decodeblock
PORT MAP (
    -- list connections between master ports and signals
b_Input => b_Input,
b_output => b_output,
CLOCK_50 => CLOCK_50
);
    init : PROCESS                                               
    -- variable declarations                                     
    BEGIN  
    b_input <= '0',
       '1' after 1.1 ns,
       '0' after 2.9 ns,                                                     
       '1' after 5.1 ns,
       '0' after 7.6 ns, 
       '1' after 9.9 ns, 
       '0' after 12.5 ns, 
       '1' after 15.4 ns, 
       '0' after 18.6 ns, 
       '1' after 22.1 ns, 
       '0' after 25.9 ns, 
       '1' after 29.7 ns, 
       '0' after 33.8 ns, 
       '1' after 38.2 ns;

        -- variable declarations                                                                                            
        for i in 1 to num_clk_cycles loop
        CLOCK_50 <= not CLOCK_50;          
        wait for clk_period/2; 
        CLOCK_50 <= not CLOCK_50;     
        wait for clk_period/2;      
        end loop;                       
        WAIT;                                                    
        END PROCESS init;                                          
        always : PROCESS                                              
        -- optional sensitivity list                                  
        -- (        )                                                 
        -- variable declarations                                      
        BEGIN                                                         
    -- code executes for every event on sensitivity list  
        WAIT;                                                        
        END PROCESS always;                                          
        END decodeblock_arch;
  • How often does your `bounce_a` input toggle? If you have `counter_size` set to `8` and the `clk` period is `20 ns`, the `result` would take `20*(10^-9) * 2^8 = 5.12 us` to toggle if `bounce_a` was static. For testing, I would make `counter_size` something much smaller, so that you can see the design working in a shorter amount of time. – scary_jeff Jun 07 '16 at 13:17
  • I'm not exactly sure about how often the `bounce_a` input toggles. It's a rotary encoder input that acts as an 8-bit up/down counter so, the hardware implemented should count forwards 8 times to the max count and backwards 8 times to the zero count – Nathan Piper Jun 07 '16 at 14:45
  • I meant how often does it toggle in the simulation. If it's more often than every 5.12 us, it will appear to do nothing. – scary_jeff Jun 07 '16 at 15:55
  • Yeah, I thought that's what you meant so I included the testbench code. As you can see, `bounce_a` toggles with random intervals that are less then 5.12 us. Is my schematic okay? – Nathan Piper Jun 07 '16 at 16:06
  • `bounce_a` must be stable for longer than 5.12 us for the circuit to register the new level. Try setting `counter_size` to `3`, and see if it works. – scary_jeff Jun 08 '16 at 07:27
  • Already did that, even set it to 1 and still a flat output – Nathan Piper Jun 08 '16 at 08:33

0 Answers0