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\$
  • 1
    \$\begingroup\$ As there is no clock_out in the posted code, I'm not surprised it shows no activity. \$\endgroup\$ – Brian Drummond Jan 22 '14 at 15:43
  • \$\begingroup\$ cheers brian. there is a clock. i just added entity part to the code i posted. \$\endgroup\$ – Chanuka Perera Jan 22 '14 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 '14 at 16:12
  • \$\begingroup\$ in simulation. ISIM!!! Thought of running a test bench before downloading to hardware. should that make any difference? \$\endgroup\$ – Chanuka Perera Jan 22 '14 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 '14 at 17:55
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;
|improve this answer|||||
\$\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).

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ cheers martin. i used a binary conversion tool to convert DVSR value to binary to get the width of the binary number. \$\endgroup\$ – Chanuka Perera Jan 23 '14 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.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ The incrementing signal "ms_reg", "ms_next" is type unsigned. \$\endgroup\$ – Chanuka Perera Jan 22 '14 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\$ – user2534517 Jan 22 '14 at 16:43
  • 2
    \$\begingroup\$ There is no need for std_logic_vector here. \$\endgroup\$ – Brian Drummond Jan 22 '14 at 17:15
  • \$\begingroup\$ ieee.numeric_std and the unsigned type are already being used here \$\endgroup\$ – Martin Thompson Jan 23 '14 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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