![]() |
8254 mode 2 divide by n counter
Hi, I'm losing it or seriously lacking sleep.
I have a simple circuit that is to be driven by a timer output similar to an 8254 operating in mode 2. So simple its unbelievable. However I synthesis the code below and the falling edge of clkout is always generated when the count is 0. If modulus is loaded with 3 then I expect so 3,2,1,3,2,1 repeating with the clkout going low on 1 and coming high on 0 as the reload occurs. clkout is delayed one clock. Now I realise this due to the signal queue, however if I set clkout low when count = 2 it make no difference. In fact irrespective of the compare & reload value clkout always go low when the count is 0. Any ideas anyone? library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; entity CLOCK_DIVIDER is port( reset: in std_logic; clk: in std_logic; modulus:in std_logic_vector (15 downto 0); -- modulo divider enable: in std_logic; clkout: out std_logic -- divided output ); end entity; architecture RTL of CLOCK_DIVIDER is begin pDivide: process(clk, reset, enable) variable count: natural; begin if (reset = '0') then count := 0; clkout <= '1'; elsif falling_edge(clk) then if (enable = '1') then if (count = 1) then clkout <= '0'; elsif (count = 0) clkout <= '1'; count = modulus; else count := count - 1; end if; else count := count; end if; end if; end process; end architecture RTL; |
sorry for the typo, I'm aware of the missing 'then'
|
not a good start... I copy and pasted the an early iteration of the rtl. Below is the coder I'm running. I want the same functionality as described earlier.
Changing x in the compare below make to change to when the output is asserted low. This I don't understand. if (count = to_integer(unsigned(modulus - x))) then pDivide: process(clk, reset, enable) variable count: natural; begin if (reset = '0') then count := 0; clkout <= '1'; elsif falling_edge(clk) then if (enable = '1') then if (count = to_integer(unsigned(modulus))) then count := 0; else count := count + 1; end if; else count := count; end if; if (count = to_integer(unsigned(modulus - 2))) then clkout <= '0'; else clkout <= '1'; end if; end if; end process; |
a few hours sleep did the trick...
posted the code for review and/or use cheers, :fisheye: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; entity CLOCK_DIVIDER is port( reset: in std_logic; -- device reset clk: in std_logic; -- device clock as it run synchronous to system clock modulus:in std_logic_vector (15 downto 0); -- modulo divider enable: in std_logic; -- enable device clkout: out std_logic -- divided clock output ); end entity; architecture RTL of CLOCK_DIVIDER is signal eSync: std_logic; signal eSyncP: std_logic; begin pDivide: process(clk, reset, enable) variable count: natural; variable reload: natural; begin if (reset = '0') then clkout <= '1'; elsif falling_edge(clk) then eSync <= enable; eSyncP <= eSync; -- catch rising edge of timer being started and -- set counter with reload value & deassert output if ((eSync = '1') and (eSyncP = '0')) then reload := to_integer(unsigned(modulus)); -- load the counter count := reload; elsif (enable = '1') then count := count - 1; if (count = 1) then clkout <= '0'; elsif (count = 0) then clkout <= '1'; count := reload; end if; else count := count; end if; end if; end process; end architecture RTL; |
| All times are GMT. The time now is 08:06 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.