0

I'm a analogue engineer trying to learn VHDL for a project i have. the project is to count the rising edge of a input signal and prescale the counts to a smaller number. for example if there are 8 counts on the input then 1 count will be outputted. the prescale value can be user changed. i have managed to work the prescale part out but at pressent the output will constantly go high .

what i am trying to do is once the prescale count is = to the user selected value then a 500 ns pulse is outputted rather then the constant logic high.

i have a 50 MHz clk, so the output needs to stay high for 25 lock cycles, however i am unsure how to to do this.

any help would be great :)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity counter is
port (
    pushbutton: in std_logic;
    SW: in std_logic_vector(7 downto 0); -- user select switches
    RESET: in std_logic;
    OUTPUT: out std_logic;
    LEDS: out std_logic_vector(8 downto 0) -- un used leds

);
end counter;

architecture Behavioral of counter is
signal COUNTER: std_logic;
signal PRESCALER: std_logic_vector(7 downto 0);
signal SWITCH: std_logic_vector(7 downto 0);
begin

CounterProcess: process(RESET, pushbutton)
begin
    if rising_edge(pushbutton) then
        if RESET = '0' then
            PRESCALER <= (others => '0');
            COUNTER <= '0';
        else        
            if PRESCALER < SWITCH - 1 then
            PRESCALER <= PRESCALER + 1;
            else
                PRESCALER <= (others => '0');
                COUNTER <= '1';
                end if;
        end if;
    end if;
end process;

LEDS <= (others => '0'); -- Turn off all unsed LEDs
SWITCH <= SW; -- Asign switch value into a signal 
OUTPUT <= COUNTER; 

end Behavioral;
Liam
  • 1
  • 2

1 Answers1

0

If I understand the problem correctly, if the 'SW' signal is set to 8, you should be able to press 'pushbutton' seven times while nothing happens. On the eight time, a 500 ns pulse should appear on 'OUTPUT'.

Looks like you've got the reset right, but where's the clock? You've got to bring the clock in through the entity. That the rising_edge(pushbutton) is working is actually odd, because buttons typically needs debouncing. That is, once you press the button, the CounterProcess would register many rising edges before the signal settles. Also, COUNTER is only set to '0' when the module is reset, therefore it will get stuck at '1' during normal operation.

This problem as I see it is best divided into three processes. A process for debouncing the pushbutton input. A prescaler process which takes the debounced signal and the SW signal as input, and outputs a toggle signal when the button pushes have been counted to the value of SW. The last process would be take the toggle signal as an input, and produce an 500 ns pulse on OUTPUT.

For the CounterProcess, you are on to something, and I'm sure you will figure it out. But do yourself a favor, and make all processes synchronous:

debounce : process(clk)
  constant max_count : natural := 127;
  variable counter : natural;
  variable prev : std_logic;
begin
  if rising_edge(clk) then
    if rst = '1' then
      -- reset all
    else

      -- if pushbutton is != prev then
      -- check if counter is > max_count, if not we assume
      -- it is still bouncing. if counter is > max_count we
      -- assume this is a new press of the button, so we
      -- toggle the output:
      -- debounced_toggle <= not debounced_toggle;

      prev := pushbutton;
    end if;
  end if;
end process;

CounterProcess: process(clk)
  variable prev : std_logic;
  variable counter : natural;
begin
  if rising_edge(clk) then
    if rst = '1' then
      -- reset all
    else

      -- when debounced_toggle != prev, do your magic
      -- and increment the counter

      -- when counter reaches the value of SW,
      -- reset the counter and toggle the output:
      -- output_toggle <= not output_toggle

      prev := debounced_toggle;
    end if;
  end if;
end process;

output_pulse : process(clk)
  constant max_count : natural := 25;
  variable counter : integer;
  variable prev : std_logic;
begin
  if rising_edge(clk) then
    if rst = '1' then
      -- reset all incl OUTPUT
    else
      OUTPUT <= '0'; -- '0' if not overwritten later in process

      -- if output_toggle != prev,
      -- hold OUTPUT for 25 clock cycles

      prev := debounced_toggle;
    end if;
  end if;
end process;
ni9e
  • 151
  • 1
  • 11