8 Bit Up/Down Counter Version 3.2.0 Jenniffer Estrada Project 3 EE365 Advanced Digital Design Prof. Khondker October 23, 2008 Executive Summary An eight bit up down counter was implemented on the Altera DE1 Board. The counter ran on an effective 1 Hertz clock. A direction key, Key0, changed the counting direction depending on whether it is pressed. A clear button, Key 1, reset the counter to 0x00 and a hold button, Key 2, held the value in the counter when pressed. The load button, Key 3, loaded an eight bit number based on the position of switches 0 through 7. The output displayed two hexadecimal numbers on two seven segment displays and on eight LEDs. The design was tested and debugged using SignalTap II, and meets all the specifications. Problem Description Design a 8-bit binary up-down counter for a 1 Hz effective clock. The counter should count down when button KEY0 is pressed and should count up when it is released. It should have a clear button (KEY1) that initializes the sequence (asynchronously) to 0X00 when it is pressed. Also it has a count button (KEY2) which disables the counting sequence when it is pressed. When button KEY3 is pressed, it stops counting & loads (synchronously) a 8-bit number (N) into the counter. The 8-bit number to be loaded is provided using the 8 switches (SW7-SW0) on the DE1 board. The counting process will repeat itself between 0 and N in the up sequence and between N and 0 in the down counting sequence. The output should be displayed on the LEDs on the DE1 board as well as on the 7 segment displays. The least significant bit (LSB) of the counter should be displayed on LEDR0 and the MSB on LEDR7. The 7-seqment displays should use 2 HEX numbers to represent the 8 bit numbers. In this design you must instantiate a SignalTap II logic Analyzer as a tool for debugging your design. Design Problem Statement The binary up down counter is enabled after 50,000,000 pulses from the 50MHerts clock within the DE1 board. When the button Key 0 is pressed (set to 0), the counter will initiate the downward counting sequence until released, where it will resume counting up. When the button Key 1 is pressed, the counter will reset to the value 0x00 without waiting for the effective clock rising edge. Key 2 will hold the value that the counter has stored for as long as the button is pressed. Key 3 will synchronously stop the counter, load and set the maximum value for the counter as the number selected by the eight switches, SW(0)SW(7), and hold the value until released, where it will resume the counting. The output of the counter will be displayed both on two seven segment displays as Hexadecimal numbers as well as 8 LEDs on the DE1 board. The two unused seven segment displays will be turned off and SignalTap II will be used as a debugging tool for the counter. Problem Decomposition Project3 “1111111” Hex 3 ClockCounter CLOCK_50 50MHz EffClk Hex 2 CountEnable Key 0 DecodeHex UpDownCounterHold Key 1 Enable Key 2 Key 3 BitInput Hex 1 7 Hex 0 4 Direction Reset Output Hold SW(0-7) 7 CountValue 8 DecodeHex 4 Load BitInput Max LEDR(7-0) CountMax EightBitRegister load Output Vector Fig.1. Block Diagram of the Eight Bit Up Down Counter Complying with the design specifications, the top level entity project3, inputs to our system are the 50MHs clock in the DE1 board, Keys 0-3, Switches 0 to 7. The “1111111” input is used to keep the unused 7 segment displays, Hex3 and Hex2, off all the time. The components, ClockCounter, UpDownCounterHold and EightBitRegister, all see the 50Mhz clock. ClockCounter uses Clock_50 to output the effective clock, EffClk, which enables UpDownCounterHold. Key0 controls the direction of the counting, Key1 controls the reset of the counter to 0x00, Key2 controls the loading of the 8 bit number determined by Switches 0 to 7, SW(0-7), and Key3 controls the hold of the current value in the counter when pressed. The loaded number from the EightBitRegister will become the maximum value that the counter can count to before resetting to zero. CountEnable, CountMax and CountValue are signals within the design. The DecodeHex, instantiated for the two 7 segment displays that will be in use, will use as input, BitInput, the value outputted by UpDownCounterHold through the signal, CountValue. The signal CountValue will give the binary number to LEDR(7-0) to display in the 8 LEDs on the DE1 board, and the 8 bit number will also be divided from 0 to 3 and 3-7 and sent to the corresponding to the appropriate DecodeHex to be displayed in the 7 segment display on the DE1 board. Significant Details of Design Process The design is written to be modular to make it possible for future use in other projects. The Top Level Entity, project3, has four components, ClockCounter, UpDownCounterHold, EightBitRegister, DecodeHex. ClockCounter.vhd uses the 50Mhz clock from the DE1 board to count 50000000 pulses to synchronously enable the UpDownCounter at 1Hertz. EightBitRegister.vhd uses the effective clock to load in an eight bit binary vector defined by the user input of the switches 7 down to 0 and feeds the value to the UpDownCounterHold as the maximum value that it can count to until resetting to zero. UpDownCounterHold.vhd, is an eight bit counter enabled by ClockCounter. The component has 7 inputs. When is Key 1 has a value of ‘0’, pressed, the counter asynchronously resets to 00, which means that it can be triggered on either edge of the clock. The counting direction is determined by Key0. When Key0 is pressed, the counting decreases by one on every clock edge of the effective clock. The counter holds the current value as long as Key2 is pressed. The counter stops the counting sequence and synchronously loads the binary number from the output of EightBitRegister when Key3 is pressed and sets the new value to be the maximum value. The output of the counter is split two different paths, going to the LEDR input and breaking off again into 4 bit and input into the corresponding DecodeHex components. The LEDR will display the 8 bit binary input with LEDR0 being the LSB and LEDR7 being the MSB. DecodeHex.vhd takes the four bit binary vector and acts as a 4 to 7 Multiplexer, displaying the corresponding hexadecimal number on the 7 segment display. The top level entity uses structural architecture and instantiates the component DecodeHex twice. The input, “1111111” is used to disable the unused 7 segment displays. The LEDR uses the signal, CountValue to display the 8 bit binary number on the LEDs. Alternative Designs An Alternative design that could have been implemented was to set the upper bound of our ClockCounter to 49999999 and then instead of using UpperBound-1, we can use UpperBound. An Example of this would be: …. COMPONENT ClockCounter IS GENERIC ( UpperBound: integer:=49999999); PORT( Clock: IN std_logic; Enable: IN std_logic; EffClk: OUT std_logic); END COMPONENT ClockCounter; …. ARCHITECTURE behavior OF ClockCounter IS signal count : integer range 0 to(UpperBound-1); BEGIN PROCESS (Clock) BEGIN IF (rising_edge(Clock) and Enable = '1') then IF( count = (UpperBound-1)) then count <= 0; EffClk <= '1'; else count <= count+1; EffClk <= '0'; end if; end if; END PROCESS; …. The design could be modified to run completely synchronous to avoid glitches. Instead of using signals, INOUT statements could be used within the design to store data. Design Documentations: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; ENTITY project3 IS PORT( CLOCK_50: KEY: SW: HEX0,HEX1: HEX2,HEX3: LEDR: END project3; IN std_logic; IN std_logic_vector(3 downto 0); IN std_logic_vector(7 downto 0); OUT std_logic_vector(6 downto 0); OUT std_logic_vector(6 downto 0); OUT std_logic_vector(7 downto 0)); ARCHITECTURE structural OF project3 IS COMPONENT DecodeHex IS PORT( BitInput: IN std_logic_vector(3 downto 0); HexOutput: OUT std_logic_vector(6 downto 0)); END COMPONENT DecodeHex; COMPONENT ClockCounter IS GENERIC ( UpperBound: integer:=50000000); PORT( Clock: IN std_logic; Enable: IN std_logic; EffClk: OUT std_logic); END COMPONENT ClockCounter; COMPONENT UpDownCounterHold IS PORT ( Clock: IN std_logic; Enable: IN std_logic; Reset: IN std_logic; Direction: IN std_logic; Hold: IN std_logic; Load: IN std_logic; Max: IN std_logic_vector(7 DOWNTO 0); Output: OUT std_logic_vector(7 DOWNTO 0)); END COMPONENT UpDownCounterHold; COMPONENT EightBitRegister IS PORT ( Clock: IN std_logic; Vector: IN std_logic_vector(7 DOWNTO 0); Load: IN std_logic; Output: OUT std_logic_vector(7 DOWNTO 0)); END COMPONENT EightBitRegister; signal CountEnable: signal CountValue: signal CountMax: std_logic; std_logic_vector(7 downto 0); std_logic_vector(7 downto 0); BEGIN ClockCounter0 : ClockCounter port map( Clock => CLOCK_50, Enable => '1', EffClk => CountEnable ); Counter : UpDownCounterHold port map( Clock => CLOCK_50, Enable => CountEnable, Reset => KEY(1), Direction => KEY(0), Hold => KEY(2), Load => KEY(3), Max => CountMax, Output => CountValue); CounterMaximum: EightBitRegister port map( Hex_0: DecodeHex port map( Hex_1: DecodeHex port map( Clock => CLOCK_50, Vector =>SW(7 downto 0), Load =>KEY(3), Output => CountMax); BitInput => CountValue(3 downto 0), HexOutput => HEX0); BitInput => CountValue(7 downto 4), HexOutput => HEX1); LEDR <= CountValue; HEX2 <= "1111111"; HEX3 <= "1111111"; END structural; Top Level Entity project3 VHDL Code library ieee; use ieee.std_logic_1164.all; ENTITY DecodeHex IS PORT( BitInput: IN std_logic_vector(3 downto 0); HexOutput: OUT std_logic_vector(6 downto 0)); END DecodeHex; ARCHITECTURE Behavior OF DecodeHex IS BEGIN WITH BitInput SELECT HexOutput <= "1000000" WHEN "0000", "1111001" WHEN "0001", "0100100" WHEN "0010", "0110000" WHEN "0011", "0011001" WHEN "0100", "0010010" WHEN "0101", "0000010" WHEN "0110", "1111000" WHEN "0111", "0000000" WHEN "1000", "0011000" WHEN "1001", "0001000" WHEN "1010", "0000011" WHEN "1011", "1000110" WHEN "1100", "0100001" WHEN "1101", "0000110" WHEN "1110", "0001110" WHEN "1111", "1111111" WHEN others; END Behavior; DecodeHex Component VHDL Code library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; ENTITY ClockCounter IS GENERIC (UpperBound: integer); PORT ( Clock: IN std_logic; Enable: IN std_logic; EffClk: OUT std_logic ); END ClockCounter; ARCHITECTURE behavior OF ClockCounter IS signal count : integer range 0 to(UpperBound-1); BEGIN PROCESS (Clock) BEGIN IF (rising_edge(Clock) and Enable = '1') then IF( count = (UpperBound-1)) then count <= 0; EffClk <= '1'; else count <= count+1; EffClk <= '0'; end if; end if; END PROCESS; END behavior; ClockCounter Component VHDL Code library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; ENTITY UpDownCounterHold IS PORT ( Clock: Enable: Reset: Direction: Hold: Load: Max: Output: ); END UpDownCounterHold; IN std_logic; IN std_logic; IN std_logic; IN std_logic; IN std_logic; IN std_logic; IN std_logic_vector(7 DOWNTO 0); OUT std_logic_vector(7 DOWNTO 0) ARCHITECTURE behavior OF UpDownCounterHold IS signal count : std_logic_vector(7 downto 0); BEGIN PROCESS(Clock) BEGIN IF (Reset = '0') THEN count <= "00000000"; ELSIF (rising_edge(Clock) AND Enable = '1') THEN IF (Hold = '0') THEN count <= count; ELSIF (Load = '0') THEN count <= Max; ELSIF (Load = '1' AND Direction = '1') THEN count <= count + 1; IF (count+1 > Max) THEN count <= "00000000"; END IF; ELSIF (Load = '1' AND Direction = '0') THEN count <= count - 1; IF (count-1 > Max) THEN count <= Max; END IF; ELSE count <= count; END IF; END IF; Output <= count; END PROCESS; END Behavior; UpDownCounterHold Component VHDL Code library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; ENTITY EightBitRegister IS PORT ( Clock: Vector: Load: Output: ); END EightBitRegister; IN std_logic; IN std_logic_vector(7 DOWNTO 0); IN std_logic; OUT std_logic_vector(7 DOWNTO 0) ARCHITECTURE behavior OF EightBitRegister IS signal vector_value : std_logic_vector(7 downto 0); BEGIN PROCESS(Clock) BEGIN IF (rising_edge(Clock) AND Load = '0') THEN vector_value <= Vector; ELSE vector_value <= vector_value; END IF; Output <= vector_value; END PROCESS; END behavior; EightBitRegister Component VHDL Code Performance Results and Analysis Fig.2. Quartus Resource Summary with SignalTap II Analyzer The resource summary without the SignalTap II Analyzer uses about one percent of the board. The inclusion of the debugging tool increases the memory bits used significantly, but still uses only 5 percent of the entire board. Fig.3.SignalTap II results for Key0 Figure 3 shows that when Key 0 is pressed, the counting downward counting sequence is initiated, as to be expected. Fig.4.SignalTap II results for Key1 Figure 4 shows that when Key 1 is pressed, the counter is reset to 0, which is what we expect to happen. Fig.5.SignalTap II results for Key2 Figure 5 shows the value of the counter being held when Key 2 is pressed, which is what we expect. Fig.6.SignalTap II results for Key3 when loaded number is 18 Figure 6 demonstrates the number 18 being synchronously loaded into the counter when Key 3 is pressed and holds the value while pressed, which is what we desired with our design. Using SignalTap II Analyzer, the eight bit up down counter was able to be debugged in real time to catch any glitches or wrong outputs that might go unchecked otherwise. References “VHDL Tutorials” SignalTap II with VHDL Designs. (July 31, 2008). ftp://ftp.altera.com/up/pub/Tutorials/DE2/Digital_Logic/tut_signaltapII_vhdlDE2.pdf (Retrieved on October 23, 2008). Khondker, A., “Project 4” Design Specificaions. (Fall 2008). http://people.clarkson.edu/~khondker/ee365_f2008.html (Retrieved on October 23, 2008).