--------------------------------------------------------------------------------------------------------------- -- RISA Project -- Author: A.Greensted -- Module: Counter -- Description: Counter Module -- History: --------------------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library CommonLib; use CommonLib.CommonPkg.all; entity Counter is port ( clk : in std_logic; enable : in std_logic; nReset : in std_logic; dIn : in std_logic_vector(15 downto 0); controlRegWEn : in std_logic; controlRegOut : out std_logic_vector(15 downto 0); counterWEn : in std_logic; counterOut : out std_logic_vector(15 downto 0); compareReg0WEn : in std_logic; compareReg0Out : out std_logic_vector(15 downto 0); compareReg1WEn : in std_logic; compareReg1Out : out std_logic_vector(15 downto 0); extCountEn : in std_logic; overflowIF : out std_logic; match0IF : out std_logic; match1IF : out std_logic; match0Out : out std_logic; match1Out : out std_logic); end Counter; architecture General of Counter is signal count : unsigned(15 downto 0); signal compareReg0 : std_logic_vector(15 downto 0); signal compareReg1 : std_logic_vector(15 downto 0); -- Controls: Counter input signal counterEn : std_logic; signal extPulseGenEn : std_logic; signal extSel : std_logic; signal prescalerReset : std_logic; signal prescalerSel : std_logic_vector(2 downto 0); signal counterMaxEn : std_logic; signal counterMaxSel : std_logic; signal latchReset : std_logic; signal toggle1ResetSel : std_logic; signal waveform1Sel : std_logic; signal toggle0ResetSel : std_logic; signal waveform0Sel : std_logic; signal extCountEnPulse : std_logic; signal countEn : std_logic; -- Prescaler outputs signal count1 : std_logic; signal count3 : std_logic; signal count15 : std_logic; signal count63 : std_logic; signal count255 : std_logic; signal count1023 : std_logic; signal count2047 : std_logic; signal scalerOut : std_logic; signal scaledCountEn : std_logic; signal counterReset : std_logic; signal counterOverflow : std_logic; -- Compare signal cmpMatch0 : std_logic; signal matchPulse0 : std_logic; signal matchLatch0 : std_logic; signal cmpMatch1 : std_logic; signal matchPulse1 : std_logic; signal matchLatch1 : std_logic; signal zeroMatch : std_logic; begin counterOut <= std_logic_vector(count); compareReg0Out <= compareReg0; compareReg1Out <= compareReg1; controlRegOut(15 downto 14)<= (others => '0'); controlRegOut(13) <= counterEn; controlRegOut(12) <= extPulseGenEn; controlRegOut(11) <= extSel; controlRegOut(10) <= '0'; -- prescalerReset always reads as '0' controlRegOut(9 downto 7) <= prescalerSel; controlRegOut(6) <= counterMaxEn; controlRegOut(5) <= counterMaxSel; controlRegOut(4) <= '0'; -- latchReset always reads as '0' controlRegOut(3) <= toggle1ResetSel; controlRegOut(2) <= waveform1Sel; controlRegOut(1) <= toggle0ResetSel; controlRegOut(0) <= waveform0Sel; -- RegWriteControl ------------------------------------------------------------------------------------------- -- Controls writing to Counter, control and compare registers --------------------------------------------------------------------------------------------------------------- RegWriteControl : process(clk) begin if (clk'event and clk='1') then prescalerReset <= '0'; -- reset this to zero latchReset <= '0'; -- reset this to zero if (nReset='0') then counterEn <= '0'; extPulseGenEn <= '0'; extSel <= '0'; prescalerReset <= '0'; prescalerSel <= b"000"; counterMaxEn <= '0'; counterMaxSel <= '0'; latchReset <= '0'; toggle1ResetSel <= '0'; waveform1Sel <= '0'; toggle0ResetSel <= '0'; waveform0Sel <= '0'; compareReg0 <= (others => '0'); compareReg1 <= (others => '0'); elsif (enable='1') then -- Control Reg Write if (controlRegWEn='1') then counterEn <= dIn(13); extPulseGenEn <= dIn(12); extSel <= dIn(11); prescalerReset <= dIn(10); prescalerSel <= dIn(9 downto 7); counterMaxEn <= dIn(6); counterMaxSel <= dIn(5); latchReset <= dIn(4); toggle1ResetSel <= dIn(3); waveform1Sel <= dIn(2); toggle0ResetSel <= dIn(1); waveform0Sel <= dIn(0); end if; -- Compare Reg 0 Write if (compareReg0WEn='1') then compareReg0 <= dIn; end if; -- Compare Reg 1 Write if (compareReg1WEn='1') then compareReg1 <= dIn; end if; end if; end if; end process RegWriteControl; -- ExtCountEnPulseGenerator ----------------------------------------------------------------------------------- -- Converts the external count enable into a single clock cycle pulse --------------------------------------------------------------------------------------------------------------- ExtCountEnPulseGenerator : PulseGenerator port map ( clk => clk, nReset => nReset, enable => enable, input => extCountEn, pulse => extCountEnPulse); -- CountEnPreFilter ------------------------------------------------------------------------------------------- -- Deals with count enable section and overal counter enable --------------------------------------------------------------------------------------------------------------- CountEnPreFilter : process(extCountEn, extPulseGenEn, extCountEnPulse, extSel, counterEn) variable en : std_logic; begin en := extCountEn; if (extPulseGenEn='1') then en := extCountEnPulse; end if; if (extSel='0') then en := '1'; end if; if (counterEn='0') then en := '0'; end if; countEn <= en; end process CountEnPreFilter; -- PrescaleCounter -------------------------------------------------------------------------------------------- -- Used to prescale the enable pulses. for counter longer periods, at lesser resolution --------------------------------------------------------------------------------------------------------------- PrescaleCounter : process(clk) variable count : unsigned(10 downto 0); begin if (clk'event and clk='1') then if (nReset='0' or prescalerReset='1' or counterWEn='1') then count := (others => '0'); count1 <= '0'; count3 <= '0'; count15 <= '0'; count63 <= '0'; count255 <= '0'; count1023 <= '0'; count2047 <= '0'; elsif (enable='1' and countEn='1') then count := count + 1; count1 <= '0'; count3 <= '0'; count15 <= '0'; count63 <= '0'; count255 <= '0'; count1023 <= '0'; count2047 <= '0'; if (count(0)='1') then count1 <= '1'; end if; if (count(1 downto 0)=b"11") then count3 <= '1'; end if; if (count(3 downto 0)=b"1111") then count15 <= '1'; end if; if (count(5 downto 0)=b"11_1111") then count63 <= '1'; end if; if (count(7 downto 0)=b"1111_1111") then count255 <= '1'; end if; if (count(9 downto 0)=b"11_1111_1111") then count1023 <= '1'; end if; if (count(10 downto 0)=b"111_1111_1111") then count2047 <= '1'; end if; end if; end if; end process PrescaleCounter; -- ScaleSelector ---------------------------------------------------------------------------------------------- -- Mux to select the require prescale ammount --------------------------------------------------------------------------------------------------------------- ScaleSelector: scalerOut <= countEn when prescalerSel = b"000" else count1 when prescalerSel = b"001" else count3 when prescalerSel = b"010" else count15 when prescalerSel = b"011" else count63 when prescalerSel = b"100" else count255 when prescalerSel = b"101" else count1023 when prescalerSel = b"110" else count2047 when prescalerSel = b"111" else '0'; scaledCountEn <= countEn and scalerOut; -- Counter ---------------------------------------------------------------------------------------------------- -- The actual Counter --------------------------------------------------------------------------------------------------------------- Counter : process(clk) variable countVar : unsigned(15 downto 0); variable overflow : std_logic; begin if (clk'event and clk='1') then if (nReset='0') then countVar := (others => '0'); overflow := '0'; elsif (enable='1') then if (counterWEn='1') then countVar := unsigned(dIn); overflow := '0'; elsif (scaledCountEn='1') then if (counterReset='1') then countVar := (others => '0'); overflow := '0'; else countVar := countVar + 1; if (countVar=x"0000") then overflow := '1'; else overflow := '0'; end if; end if; end if; end if; end if; count <= countVar; counterOverflow <= overflow; end process Counter; -- Match Units ------------------------------------------------------------------------------------------------ -- Generates the match signals --------------------------------------------------------------------------------------------------------------- cmpMatch0 <= '1' when (count=unsigned(compareReg0) and counterEn='1') else '0'; cmpMatch1 <= '1' when (count=unsigned(compareReg1) and counterEn='1') else '0'; zeroMatch <= '1' when count=x"0000" else '0'; -- MatchOutputGenerator --------------------------------------------------------------------------------------- -- Generates the match pulse and toggle outputs --------------------------------------------------------------------------------------------------------------- MatchOutputGenerator : process(clk, cmpMatch0, cmpMatch1, zeroMatch, toggle0ResetSel, toggle1ResetSel) variable pulseReg0 : std_logic; variable latchReg0 : std_logic; variable reset0 : std_logic; variable pulseReg1 : std_logic; variable latchReg1 : std_logic; variable reset1 : std_logic; begin if (toggle0ResetSel='1') then reset0 := cmpMatch1; else reset0 := zeroMatch; end if; if (toggle1ResetSel='1') then reset1 := cmpMatch0; else reset1 := zeroMatch; end if; if (clk'event and clk='1') then if (nReset='0') then pulseReg0 := '0'; latchReg0 := '0'; pulseReg1 := '0'; latchReg1 := '0'; elsif (enable='1') then pulseReg0 := cmpMatch0; pulseReg1 := cmpMatch1; if (reset0='1' or latchReset='1') then latchReg0 := '0'; elsif (cmpMatch0='1') then latchReg0 := '1'; end if; if (reset1='1' or latchReset='1') then latchReg1 := '0'; elsif (cmpMatch1='1') then latchReg1 := '1'; end if; end if; end if; matchPulse0 <= cmpMatch0 and (not pulseReg0); matchLatch0 <= (cmpMatch0 or latchReg0) and (not reset0); matchPulse1 <= cmpMatch1 and (not pulseReg1); matchLatch1 <= (cmpMatch1 or latchReg1) and (not reset1); end process MatchOutputGenerator; -- Match Output ----------------------------------------------------------------------------------------------- -- Waveform output selection and interrupt flag output --------------------------------------------------------------------------------------------------------------- match0Out <= matchPulse0 when (waveform0Sel='1') else matchLatch0; match0IF <= matchPulse0; match1Out <= matchPulse1 when (waveform1Sel='1') else matchLatch1; match1IF <= matchPulse1; -- CounterMaxControl ------------------------------------------------------------------------------------------ -- --------------------------------------------------------------------------------------------------------------- CounterMaxControl : process(counterMaxEn, counterMaxSel, cmpMatch0, cmpMatch1) variable cReset : std_logic; begin if (counterMaxSel='1') then cReset := cmpMatch1; else cReset := cmpMatch0; end if; if (counterMaxEn='0') then cReset := '0'; end if; counterReset <= cReset; end process; OverflowPulseGenerator : PulseGenerator port map ( clk => clk, nReset => nReset, enable => enable, input => counterOverflow, pulse => overflowIF); end General;