Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16623 Discussions

Generate a pulse by using a counter/timer

Altera_Forum
Honored Contributor II
1,766 Views

Hello, 

I just started with FPGAs and thus I am trying to improve my VHDL skills. Recently I am building a design that generates a pulse which is meant to start a ADC conversion. My idea is to use a counter which controls the pulse length. Unfortunately, the counter seems to start but never reaches the value at which the pulse should end. After several hours of trying I have no clue what is going wrong. May you could have a look at my code. 

 

So this is my counter: 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity counter is generic ( n : natural := 1 ); port ( clock : in std_logic; clock_enable : in std_logic; reset : in std_logic; output : out std_logic_vector((n-1) downto 0) ); end; architecture behaviour of counter is signal counter_value : std_logic_vector((n-1) downto 0) := (others => '0'); begin process(clock, reset) begin if (reset = '1') then counter_value <= (others => '0'); elsif (rising_edge(clock)) then if (clock_enable = '1') then counter_value <= counter_value + 1; end if; end if; end process; output <= counter_value; end behaviour; 

 

And here is my ADC design file, which uses the counter: 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ti_ads1675 is port ( -- ports required by the TI ADS1675 start : out std_logic; -- ports required by the avalon-mm interface clock : in std_logic; reset_n : in std_logic; read : in std_logic; write: in std_logic; address: in std_logic; writedata : in std_logic_vector(31 downto 0); readdata : out std_logic_vector(31 downto 0) ); end ti_ads1675; architecture rtl of ti_ads1675 is component counter is generic ( n : natural := 1 ); port ( clock : in std_logic; clock_enable : in std_logic; reset : in std_logic; output : out std_logic_vector(n downto 0) ); end component; -- counter related signals signal counter_clock_enable : std_logic := '0'; signal counter_reset : std_logic := '1'; signal counter_value : std_logic_vector(31 downto 0); -- general signals signal control_register : std_logic_vector(31 downto 0) := x"00000000"; signal data_register : std_logic_vector(31 downto 0); begin counter_inst : component counter generic map ( n => 32 ) port map ( clock => clock, clock_enable => counter_clock_enable, reset => counter_reset, output => counter_value ); registers : process (clock) begin if (rising_edge(clock)) then -- reset registers if (reset_n = '0') then data_register <= x"00000000"; control_register <= x"00000000"; readdata <= x"00000000"; -- read register contents elsif (read = '1') then if (address = '0') then readdata <= data_register; elsif (address = '1') then readdata <= control_register; end if; -- write register contents elsif (write = '1') then if (address = '0') then data_register <= writedata; elsif (address = '1') then control_register <= writedata; end if; end if; end if; end process registers; -------------------------- -- gererate start pulse -- -------------------------- process (control_register(2), counter_value) begin if (rising_edge(control_register(2))) then counter_reset <= '0'; counter_clock_enable <= '1'; start <= '1'; elsif (counter_value = x"0000ffff") then start <= '0'; counter_clock_enable <= '0'; counter_reset <= '1'; control_register(2) <= '0'; end if; end process; end rtl; 

 

I have absolutely no clue what is wrong here. The counter itself works, so I think I made a (logic?) fault in my ADC design file. I am thankful for any tips or hints. 

 

Regards Michael
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
800 Views

Hi,  

 

At least one problem is in line: 

 

if (rising_edge(control_register(2))) then 

 

do not use rising_edge function to detect rising edge of general signal of your design. rising_edge function ment to be used for CLOCK edge detection.  

 

Regards,
0 Kudos
Altera_Forum
Honored Contributor II
800 Views

This is the culprit code: 

 

-------------------------- -- gererate start pulse -- -------------------------- process (control_register(2), counter_value) begin if (rising_edge(control_register(2))) then counter_reset <= '0'; counter_clock_enable <= '1'; start <= '1'; elsif (counter_value = x"0000ffff") then start <= '0'; counter_clock_enable <= '0'; counter_reset <= '1'; control_register(2) <= '0'; end if; end process;  

 

This is not good code, so I have no idea what the synthesisor made of it. Did you look at the RTL and technology diagram? 

You should clock this with "clock", and make an edge detector circuit with control_register(2) -  

 

process(clock) begin if rising_edge(clk) then control_register2_r <= control_register(2); if control_register2_r = '0' and control_register(2) = '1' then -- you have a rising_ege on the signal  

 

Do you have a testbench to test this code in the simualtor? 

 

And as you're trying to improve your VHDL skills - stop using std_logic_arith and std_logic_unsigned. They are non-standard VHDL libraries. Use numeric_std instead.
0 Kudos
Altera_Forum
Honored Contributor II
800 Views

Hi, thank you for your fast replies. I'll have a closer look at your suggestions and try to change my code accordingly. I'll report the outcome... 

 

... with your help I just go the design running. I build an edge detector an used it to start my counter. Here is the code: 

library ieee; use ieee.std_logic_1164.all; entity edge_detector is port ( clock : in std_logic; signal_in : in std_logic; output : out std_logic ); end edge_detector; architecture behavioral of edge_detector is signal signal_delayed : std_logic; begin process (clock) begin if (rising_edge(clock)) then signal_delayed <= signal_in; end if; end process; output <= signal_in and (not signal_delayed); end behavioral; 

 

And following the updated code snippet of the ADC-Design: 

process(control_register_start_edge, counter_value) begin if (control_register_start_edge = '1') then counter_reset <= '0'; counter_clock_enable <= '1'; start <= '1'; elsif (counter_value = x"00000004") then start <= '0'; counter_clock_enable <= '0'; counter_reset <= '1'; end if; end process; 

 

I was able to verify the design with ModelSim and even used the 'start' signal to blink an LED on my BeMicro CV ;) 

 

No I am looking for a intelligent way to reset my register bit to '0' again. My first idea was to use a reset signal which would be detected in my r/w register process...  

 

So after all, thank you for your help!
0 Kudos
Reply