jonnybgood
Full Member level 4
I implemented an 8-bit Synchronous programmable counter with;
-asynchronous active low reset
-Synchronous enable
-Count up or down (with rising edge)
-Terminal counter up (for overflow)
-Terminal Counter down (underflow)
-Asynch load
-8-bit parallel load:
--counter.vhd
LIBRARY ieee;
-- STD_LOGIC and STD_LOGIC_VECTOR types, and relevant functions
use ieee.std_logic_1164.all;
-- SIGNED and UNSIGNED types, and relevant functions
use ieee.numeric_std.all;
ENTITY counter IS
PORT (
dir, cnt_en, clk : in std_logic := '0';
Reset, load : in std_logic;
p : in INTEGER RANGE 0 TO 255;
qd : inout INTEGER RANGE 0 TO 255;
TCU, TCD : out std_logic;
cnt_in : inout std_logic_vector (7 downto 0) := (others => '0');
cnt_out : out std_logic_vector (7 downto 0) := (others => '0'));
END counter;
ARCHITECTURE RTL OF counter IS
signal cnt : INTEGER RANGE 0 TO 255;
signal NotCPU : std_logic := '0';
BEGIN
cnt_out <= std_logic_vector(to_unsigned(cnt, cnt_out'length));
PROCESS (clk, Reset, p, qd, dir, cnt_en, cnt, load)
BEGIN
IF (Reset = '0') THEN
cnt <= 0;
ELSIF (load = '1' and Reset = '1') THEN --load is activated
cnt <= p;
ELSE
IF (rising_edge(clk)) THEN
IF (dir = '1' and cnt_en = '1') THEN
cnt <= cnt + 1;
TCD <= '1';
TCU <= '1';
ELSIF (dir = '0' and cnt_en = '1') THEN
cnt <= cnt - 1;
TCD <= '1';
TCU <= '1';
END IF;
END IF;
END IF;
qd <= cnt;
if cnt = 0 then
if (dir = '1') then
TCD <= '1';
TCU <= '1';
elsif (dir = '0') then
TCD <= '0';
TCU <= '1';
end if;
elsif (cnt = 255) then
if (dir = '1') then
TCD <= '1';
TCU <= '0';
elsif (dir = '0') then
TCD <= '1';
TCU <= '1';
end if;
end if;
END PROCESS;
END RTL;
_____________________________________________________________________________________________________
When I simulated with the following test bench I got results that match the Truth table in the 74HC193 data sheet. What do you think? The only problem is that although I am declaring an integer with a range, when the integer (cnt) is exceeding the maximum upper limit 255, the simulation stops instead of resetting the this integer (cnt) automatically. Do I have to take care of resetting it my self in the vhdl code?
Also, the 74HC193 implements the counters slightly different from mine. It uses two separate clocks for count up or count down. Each one is clocked while the other is held high;
I tried to follow this method but there seems to be issue when considering two possible clocks;
ELSE
IF (CPU = '1' and CPD = '1') THEN
IF (rising_edge(CPU)) THEN
cnt <= cnt + 1;
TCD <= '1';
TCU <= '1';
ELSIF (rising_edge(CPD)) THEN
cnt <= cnt - 1;
TCD <= '1';
TCU <= '1';
END IF;
END IF;
I get this error: ..behavior depends on the edges of multiple distinct clocks ..
What can be a possible solution for this?
--counter_test.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity counter_test is
end Entity counter_test;
Architecture behavioral of counter_test is
Signal dir, cnt_en, clk, TCU, TCD : std_logic := '0';
Signal Reset, load : std_logic := '1';
signal p, qd : integer range 0 to 255 ;
Signal Endsim : std_logic := '0';
Signal cnt_in, cnt_out : std_logic_vector (7 downto 0) := (others => '0');
begin
UUT : entity work.counter
port map ( clk => clk,
Reset => Reset,
load => load,
p => p,
dir => dir,
qd => qd,
TCU => TCU,
TCD => TCD,
cnt_en => cnt_en,
cnt_in => cnt_in,
cnt_out => cnt_out);
CLK_process rocess
begin
if(EndSim = '0') then
clk <= NOT clk;
wait for 2ns;
else wait;
end if;
end process;
Signals : process
Begin
wait for 0.5 ns;
Reset <= '1';
dir <= '1';
cnt_en <= '1';
load <= '0';
wait for 1020ns;
cnt_en <= '0';
wait for 50ns;
cnt_en <= '1';
dir <= '0';
wait for 1020ns;
cnt_en <= '0';
wait for 50ns;
load <= '1';
p <= 100;
wait for 4ns;
load <= '0';
cnt_en <= '1';
wait for 200ns;
Reset <= '0';
wait for 100ns;
EndSim <= '1';
wait;
end process;
end Architecture behavioral;
-asynchronous active low reset
-Synchronous enable
-Count up or down (with rising edge)
-Terminal counter up (for overflow)
-Terminal Counter down (underflow)
-Asynch load
-8-bit parallel load:
--counter.vhd
LIBRARY ieee;
-- STD_LOGIC and STD_LOGIC_VECTOR types, and relevant functions
use ieee.std_logic_1164.all;
-- SIGNED and UNSIGNED types, and relevant functions
use ieee.numeric_std.all;
ENTITY counter IS
PORT (
dir, cnt_en, clk : in std_logic := '0';
Reset, load : in std_logic;
p : in INTEGER RANGE 0 TO 255;
qd : inout INTEGER RANGE 0 TO 255;
TCU, TCD : out std_logic;
cnt_in : inout std_logic_vector (7 downto 0) := (others => '0');
cnt_out : out std_logic_vector (7 downto 0) := (others => '0'));
END counter;
ARCHITECTURE RTL OF counter IS
signal cnt : INTEGER RANGE 0 TO 255;
signal NotCPU : std_logic := '0';
BEGIN
cnt_out <= std_logic_vector(to_unsigned(cnt, cnt_out'length));
PROCESS (clk, Reset, p, qd, dir, cnt_en, cnt, load)
BEGIN
IF (Reset = '0') THEN
cnt <= 0;
ELSIF (load = '1' and Reset = '1') THEN --load is activated
cnt <= p;
ELSE
IF (rising_edge(clk)) THEN
IF (dir = '1' and cnt_en = '1') THEN
cnt <= cnt + 1;
TCD <= '1';
TCU <= '1';
ELSIF (dir = '0' and cnt_en = '1') THEN
cnt <= cnt - 1;
TCD <= '1';
TCU <= '1';
END IF;
END IF;
END IF;
qd <= cnt;
if cnt = 0 then
if (dir = '1') then
TCD <= '1';
TCU <= '1';
elsif (dir = '0') then
TCD <= '0';
TCU <= '1';
end if;
elsif (cnt = 255) then
if (dir = '1') then
TCD <= '1';
TCU <= '0';
elsif (dir = '0') then
TCD <= '1';
TCU <= '1';
end if;
end if;
END PROCESS;
END RTL;
_____________________________________________________________________________________________________
When I simulated with the following test bench I got results that match the Truth table in the 74HC193 data sheet. What do you think? The only problem is that although I am declaring an integer with a range, when the integer (cnt) is exceeding the maximum upper limit 255, the simulation stops instead of resetting the this integer (cnt) automatically. Do I have to take care of resetting it my self in the vhdl code?
Also, the 74HC193 implements the counters slightly different from mine. It uses two separate clocks for count up or count down. Each one is clocked while the other is held high;
HTML:
http://www.nxp.com/documents/data_sheet/74HC_HCT193.pdf
I tried to follow this method but there seems to be issue when considering two possible clocks;
ELSE
IF (CPU = '1' and CPD = '1') THEN
IF (rising_edge(CPU)) THEN
cnt <= cnt + 1;
TCD <= '1';
TCU <= '1';
ELSIF (rising_edge(CPD)) THEN
cnt <= cnt - 1;
TCD <= '1';
TCU <= '1';
END IF;
END IF;
I get this error: ..behavior depends on the edges of multiple distinct clocks ..
What can be a possible solution for this?
--counter_test.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity counter_test is
end Entity counter_test;
Architecture behavioral of counter_test is
Signal dir, cnt_en, clk, TCU, TCD : std_logic := '0';
Signal Reset, load : std_logic := '1';
signal p, qd : integer range 0 to 255 ;
Signal Endsim : std_logic := '0';
Signal cnt_in, cnt_out : std_logic_vector (7 downto 0) := (others => '0');
begin
UUT : entity work.counter
port map ( clk => clk,
Reset => Reset,
load => load,
p => p,
dir => dir,
qd => qd,
TCU => TCU,
TCD => TCD,
cnt_en => cnt_en,
cnt_in => cnt_in,
cnt_out => cnt_out);
CLK_process rocess
begin
if(EndSim = '0') then
clk <= NOT clk;
wait for 2ns;
else wait;
end if;
end process;
Signals : process
Begin
wait for 0.5 ns;
Reset <= '1';
dir <= '1';
cnt_en <= '1';
load <= '0';
wait for 1020ns;
cnt_en <= '0';
wait for 50ns;
cnt_en <= '1';
dir <= '0';
wait for 1020ns;
cnt_en <= '0';
wait for 50ns;
load <= '1';
p <= 100;
wait for 4ns;
load <= '0';
cnt_en <= '1';
wait for 200ns;
Reset <= '0';
wait for 100ns;
EndSim <= '1';
wait;
end process;
end Architecture behavioral;