1
\$\begingroup\$

I created a clock divider with the code below. i followed steps in prof chu's book.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity clock_divider is
Port ( reset : in  STD_LOGIC;
       clk : in  STD_LOGIC;--Clock in
       out_red : out  STD_LOGIC);--Reduced freq clock out
end clock_divider;

architecture Behavioral of clock_divider is

constant DVSR : INTEGER := 5000000;--for 1 ms tick at 50mhz clk input
signal ms_reg, ms_next : unsigned (22 downto 0);
signal ms_tick : std_logic;--tick at every 1ms

begin

process (clk)
begin
  if (clk'event and clk = '1') then
    ms_reg <= ms_next;
  end if;
end process;

ms_next <= 
       (others => '0') when (reset = '1' or ms_reg = DVSR) else
          ms_reg + 1;

ms_tick <= 
       '1' when ms_reg = DVSR else '0';

out_red <= ms_tick;
end Behavioral;

out_red is my reduced freq clock out. Test bench shows clock_out hanging at 0. Can anyone figure out where i went wrong?

\$\endgroup\$
13
  • 1
    \$\begingroup\$ As there is no clock_out in the posted code, I'm not surprised it shows no activity. \$\endgroup\$
    – user16324
    Jan 22, 2014 at 15:43
  • \$\begingroup\$ cheers brian. there is a clock. i just added entity part to the code i posted. \$\endgroup\$ Jan 22, 2014 at 15:46
  • 1
    \$\begingroup\$ Assuming a 50MHz clock the code will give a single pulse at out_red with a duration of 20ns every second. Are you sure that you have not just missed that pulse? Are you running in hardware or simulation? \$\endgroup\$
    – alexan_e
    Jan 22, 2014 at 16:12
  • \$\begingroup\$ in simulation. ISIM!!! Thought of running a test bench before downloading to hardware. should that make any difference? \$\endgroup\$ Jan 22, 2014 at 16:15
  • 1
    \$\begingroup\$ @akohlsmith There is no inherent problem in generating signals like this, whether you call it a "clock" or a "clock enable". The problem only occurs if you try to use the edge of this signal to trigger flip-flops. \$\endgroup\$
    – Joe Hass
    Mar 1, 2014 at 17:55

3 Answers 3

1
\$\begingroup\$

Your code works if you init DVSR to 50000 instead of 5000000. It will generate a pulse every 1ms with a width of clk period, this will be 0.000...01% high and 99.99..99% low To generate a clock with 50% high 50% low I would do the following.

library ieee;
use ieee.std_logic_1164.all;

entity clock_divider is

  generic (
    divider : positive := 50000);       -- for 1 ms tick at 50mhz clk input

  port (
    reset, clk : in  std_logic;         -- reset and clock in
    out_red    : out std_logic);        -- Reduced freq clock out
end entity clock_divider;

architecture implementation of clock_divider is
 signal ClockDiv : natural range 0 to divider/2 := 0;    -- clock divide counter
 signal clk_out  : std_logic;
begin  -- architecture implementation

 clock_div_p : process (clk, reset) is

 begin  -- process clock_div_p
   if reset = '1' then                 -- asynchronous reset (active high)
     ClockDiv <= 0;
     clk_out  <= '0';
   elsif clk'event and clk = '1' then  -- rising clock edge
     if (ClockDiv = divider/2) then    -- switch polarity every half period
       ClockDiv <= 0;
       clk_out  <= not clk_out;
     else
       ClockDiv <= ClockDiv +1;
       clk_out  <= clk_out;
     end if;
   end if;
 end process clock_div_p;

 out_red <= clk_out;

end architecture implementation;
\$\endgroup\$
0
\$\begingroup\$

Make sure you have the right number of bits in your variables using an assert:

assert 2**ms_reg'length > DVSR report "Insufficient bits in ms_reg" severity failure;

Or, use a natural type to store your ms_reg and ms_next signals (assuming 32 bits will definitely enough) - let the compiler worry about how many bits to allocate - the optimiser can extract that fact from the logic (in my experience).

\$\endgroup\$
1
  • \$\begingroup\$ cheers martin. i used a binary conversion tool to convert DVSR value to binary to get the width of the binary number. \$\endgroup\$ Jan 23, 2014 at 16:12
-1
\$\begingroup\$

You cannot increment std_logic_vector directly. You need to convert it to integer, increment the integer and convert back all in a process.

You need the library ieee.numeric_std. Then in a process convert to integer:

to_integer(unsigned(S));

and back to std_logic_vector:

std_logic_vector(to_unsigned(num, len));

I should also point out that this seems like bad design. You shouldn't put logic in the path of a clock signal. In FPGAs, for example, it causes small pulses(a few ps) to occur, which can trigger your synchronous logic and cause an undefined state to be loaded in the flip-flops. Instead, you should use a PLL to generate your various clock signals.

\$\endgroup\$
4
  • \$\begingroup\$ The incrementing signal "ms_reg", "ms_next" is type unsigned. \$\endgroup\$ Jan 22, 2014 at 16:18
  • \$\begingroup\$ You should still convert it to std_logic_vector before assigning it. Also, do the conversion in the process. Generally, I prefer to use the if/else statements in a process rather than when statement. It keeps concurrent and sequential things separate. \$\endgroup\$ Jan 22, 2014 at 16:43
  • 2
    \$\begingroup\$ There is no need for std_logic_vector here. \$\endgroup\$
    – user16324
    Jan 22, 2014 at 17:15
  • \$\begingroup\$ ieee.numeric_std and the unsigned type are already being used here \$\endgroup\$ Jan 23, 2014 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.