123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- ----------------------------------------------------------------------------
- -- GPIO_Demo.vhd -- Basys3 GPIO/UART Demonstration Project
- ----------------------------------------------------------------------------
- -- Author: Marshall Wingerson Adapted from Sam Bobrowicz
- -- Copyright 2013 Digilent, Inc.
- ----------------------------------------------------------------------------
- --
- ----------------------------------------------------------------------------
- -- The GPIO/UART Demo project demonstrates a simple usage of the Basys3's
- -- GPIO and UART. The behavior is as follows:
- --
- -- *The 16 User LEDs are tied to the 16 User Switches. While the center
- -- User button is pressed, the LEDs are instead tied to GND
- -- *The 7-Segment display counts from 0 to 9 on each of its 8
- -- digits. This count is reset when the center button is pressed.
- -- Also, single anodes of the 7-Segment display are blanked by
- -- holding BTNU, BTNL, BTND, or BTNR. Holding the center button
- -- blanks all the 7-Segment anodes.
- -- *An introduction message is sent across the UART when the device
- -- is finished being configured, and after the center User button
- -- is pressed.
- -- *A message is sent over UART whenever BTNU, BTNL, BTND, or BTNR is
- -- pressed.
- -- *Note that the center user button behaves as a user reset button
- -- and is referred to as such in the code comments below
- -- *A test pattern is displayed on the VGA port at 1280x1024 resolution.
- -- If a mouse is attached to the USB-HID port, a cursor can be moved
- -- around the pattern.
- --
- -- All UART communication can be captured by attaching the UART port to a
- -- computer running a Terminal program with 9600 Baud Rate, 8 data bits, no
- -- parity, and 1 stop bit.
- ----------------------------------------------------------------------------
- --
- ----------------------------------------------------------------------------
- -- Revision History:
- -- 08/08/2011(SamB): Created using Xilinx Tools 13.2
- -- 08/27/2013(MarshallW): Modified for the Nexys4 with Xilinx ISE 14.4\
- -- --added RGB and microphone
- -- 7/22/2014(SamB): Modified for the Basys3 with Vivado 2014.2\
- -- --Removed RGB and microphone
- ----------------------------------------------------------------------------
-
- library IEEE;
- use IEEE.STD_LOGIC_1164.ALL;
-
- --The IEEE.std_logic_unsigned contains definitions that allow
- --std_logic_vector types to be used with the + operator to instantiate a
- --counter.
- use IEEE.std_logic_unsigned.all;
-
- entity GPIO_demo is
- Port ( SW : in STD_LOGIC_VECTOR (15 downto 0);
- BTN : in STD_LOGIC_VECTOR (4 downto 0);
- CLK : in STD_LOGIC;
- LED : out STD_LOGIC_VECTOR (15 downto 0);
- SSEG_CA : out STD_LOGIC_VECTOR (7 downto 0);
- SSEG_AN : out STD_LOGIC_VECTOR (3 downto 0);
- UART_TXD : out STD_LOGIC;
- VGA_RED : out STD_LOGIC_VECTOR (3 downto 0);
- VGA_BLUE : out STD_LOGIC_VECTOR (3 downto 0);
- VGA_GREEN : out STD_LOGIC_VECTOR (3 downto 0);
- VGA_VS : out STD_LOGIC;
- VGA_HS : out STD_LOGIC;
- PS2_CLK : inout STD_LOGIC;
- PS2_DATA : inout STD_LOGIC
- );
- end GPIO_demo;
-
- architecture Behavioral of GPIO_demo is
-
- component UART_TX_CTRL
- Port(
- SEND : in std_logic;
- DATA : in std_logic_vector(7 downto 0);
- CLK : in std_logic;
- READY : out std_logic;
- UART_TX : out std_logic
- );
- end component;
-
- component debouncer
- Generic(
- DEBNC_CLOCKS : integer;
- PORT_WIDTH : integer);
- Port(
- SIGNAL_I : in std_logic_vector(4 downto 0);
- CLK_I : in std_logic;
- SIGNAL_O : out std_logic_vector(4 downto 0)
- );
- end component;
-
- component vga_ctrl
- Port ( CLK_I : in STD_LOGIC;
- VGA_HS_O : out STD_LOGIC;
- VGA_VS_O : out STD_LOGIC;
- VGA_RED_O : out STD_LOGIC_VECTOR (3 downto 0);
- VGA_BLUE_O : out STD_LOGIC_VECTOR (3 downto 0);
- VGA_GREEN_O : out STD_LOGIC_VECTOR (3 downto 0);
- PS2_CLK : inout STD_LOGIC;
- PS2_DATA : inout STD_LOGIC
- );
- end component;
-
-
- --The type definition for the UART state machine type. Here is a description of what
- --occurs during each state:
- -- RST_REG -- Do Nothing. This state is entered after configuration or a user reset.
- -- The state is set to LD_INIT_STR.
- -- LD_INIT_STR -- The Welcome String is loaded into the sendStr variable and the strIndex
- -- variable is set to zero. The welcome string length is stored in the StrEnd
- -- variable. The state is set to SEND_CHAR.
- -- SEND_CHAR -- uartSend is set high for a single clock cycle, signaling the character
- -- data at sendStr(strIndex) to be registered by the UART_TX_CTRL at the next
- -- cycle. Also, strIndex is incremented (behaves as if it were post
- -- incremented after reading the sendStr data). The state is set to RDY_LOW.
- -- RDY_LOW -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go low,
- -- indicating a send operation has begun. State is set to WAIT_RDY.
- -- WAIT_RDY -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go high,
- -- indicating a send operation has finished. If READY is high and strEnd =
- -- StrIndex then state is set to WAIT_BTN, else if READY is high and strEnd /=
- -- StrIndex then state is set to SEND_CHAR.
- -- WAIT_BTN -- Do nothing. Wait for a button press on BTNU, BTNL, BTND, or BTNR. If a
- -- button press is detected, set the state to LD_BTN_STR.
- -- LD_BTN_STR -- The Button String is loaded into the sendStr variable and the strIndex
- -- variable is set to zero. The button string length is stored in the StrEnd
- -- variable. The state is set to SEND_CHAR.
- type UART_STATE_TYPE is (RST_REG, LD_INIT_STR, SEND_CHAR, RDY_LOW, WAIT_RDY, WAIT_BTN, LD_BTN_STR);
-
- --The CHAR_ARRAY type is a variable length array of 8 bit std_logic_vectors.
- --Each std_logic_vector contains an ASCII value and represents a character in
- --a string. The character at index 0 is meant to represent the first
- --character of the string, the character at index 1 is meant to represent the
- --second character of the string, and so on.
- type CHAR_ARRAY is array (integer range<>) of std_logic_vector(7 downto 0);
-
- constant TMR_CNTR_MAX : std_logic_vector(26 downto 0) := "101111101011110000100000000"; --100,000,000 = clk cycles per second
- constant TMR_VAL_MAX : std_logic_vector(3 downto 0) := "1001"; --9
-
- constant RESET_CNTR_MAX : std_logic_vector(17 downto 0) := "110000110101000000";-- 100,000,000 * 0.002 = 200,000 = clk cycles per 2 ms
-
- constant MAX_STR_LEN : integer := 27;
-
- constant WELCOME_STR_LEN : natural := 27;
- constant BTN_STR_LEN : natural := 24;
-
- --Welcome string definition. Note that the values stored at each index
- --are the ASCII values of the indicated character.
- constant WELCOME_STR : CHAR_ARRAY(0 to 26) := (X"0A", --\n
- X"0D", --\r
- X"42", --B
- X"41", --A
- X"53", --S
- X"59", --Y
- X"53", --S
- X"33", --3
- X"20", --
- X"47", --G
- X"50", --P
- X"49", --I
- X"4F", --O
- X"2F", --/
- X"55", --U
- X"41", --A
- X"52", --R
- X"54", --T
- X"20", --
- X"44", --D
- X"45", --E
- X"4D", --M
- X"4F", --O
- X"21", --!
- X"0A", --\n
- X"0A", --\n
- X"0D"); --\r
-
- --Button press string definition.
- constant BTN_STR : CHAR_ARRAY(0 to 23) := (X"42", --B
- X"75", --u
- X"74", --t
- X"74", --t
- X"6F", --o
- X"6E", --n
- X"20", --
- X"70", --p
- X"72", --r
- X"65", --e
- X"73", --s
- X"73", --s
- X"20", --
- X"64", --d
- X"65", --e
- X"74", --t
- X"65", --e
- X"63", --c
- X"74", --t
- X"65", --e
- X"64", --d
- X"21", --!
- X"0A", --\n
- X"0D"); --\r
-
- --This is used to determine when the 7-segment display should be
- --incremented
- signal tmrCntr : std_logic_vector(26 downto 0) := (others => '0');
-
- --This counter keeps track of which number is currently being displayed
- --on the 7-segment.
- signal tmrVal : std_logic_vector(3 downto 0) := (others => '0');
-
- --Contains the current string being sent over uart.
- signal sendStr : CHAR_ARRAY(0 to (MAX_STR_LEN - 1));
-
- --Contains the length of the current string being sent over uart.
- signal strEnd : natural;
-
- --Contains the index of the next character to be sent over uart
- --within the sendStr variable.
- signal strIndex : natural;
-
- --Used to determine when a button press has occured
- signal btnReg : std_logic_vector (3 downto 0) := "0000";
- signal btnDetect : std_logic;
-
- --UART_TX_CTRL control signals
- signal uartRdy : std_logic;
- signal uartSend : std_logic := '0';
- signal uartData : std_logic_vector (7 downto 0):= "00000000";
- signal uartTX : std_logic;
-
- --Current uart state signal
- signal uartState : UART_STATE_TYPE := RST_REG;
-
- --Debounced btn signals used to prevent single button presses
- --from being interpreted as multiple button presses.
- signal btnDeBnc : std_logic_vector(4 downto 0);
-
- signal clk_cntr_reg : std_logic_vector (4 downto 0) := (others=>'0');
-
- signal pwm_val_reg : std_logic := '0';
-
- --this counter counts the amount of time paused in the UART reset state
- signal reset_cntr : std_logic_vector (17 downto 0) := (others=>'0');
-
- begin
-
- ----------------------------------------------------------
- ------ LED Control -------
- ----------------------------------------------------------
-
- with BTN(4) select
- LED <= SW when '0',
- "0000000000000000" when others;
-
- ----------------------------------------------------------
- ------ 7-Seg Display Control -------
- ----------------------------------------------------------
- --Digits are incremented every second, and are blanked in
- --response to button presses.
-
- --Individual and reset blanking of Anodes
- with BTN(4) select
- SSEG_AN(3 downto 0) <= btnDeBnc(3 downto 0) when '0',
- "1111" when others;
-
- --This process controls the counter that triggers the 7-segment
- --to be incremented. It counts 100,000,000 and then resets.
- timer_counter_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- if ((tmrCntr = TMR_CNTR_MAX) or (BTN(4) = '1')) then
- tmrCntr <= (others => '0');
- else
- tmrCntr <= tmrCntr + 1;
- end if;
- end if;
- end process;
-
- --This process increments the digit being displayed on the
- --7-segment display every second.
- timer_inc_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- if (BTN(4) = '1') then
- tmrVal <= (others => '0');
- elsif (tmrCntr = TMR_CNTR_MAX) then
- if (tmrVal = TMR_VAL_MAX) then
- tmrVal <= (others => '0');
- else
- tmrVal <= tmrVal + 1;
- end if;
- end if;
- end if;
- end process;
-
- --This select statement encodes the value of tmrVal to the necessary
- --cathode signals to display it on the 7-segment
- with tmrVal select
- SSEG_CA <= "01000000" when "0000",
- "01111001" when "0001",
- "00100100" when "0010",
- "00110000" when "0011",
- "00011001" when "0100",
- "00010010" when "0101",
- "00000010" when "0110",
- "01111000" when "0111",
- "00000000" when "1000",
- "00010000" when "1001",
- "11111111" when others;
-
-
- ----------------------------------------------------------
- ------ Button Control -------
- ----------------------------------------------------------
- --Buttons are debounced and their rising edges are detected
- --to trigger UART messages
-
-
- --Debounces btn signals
- Inst_btn_debounce: debouncer
- generic map(
- DEBNC_CLOCKS => (2**16),
- PORT_WIDTH => 5)
- port map(
- SIGNAL_I => BTN,
- CLK_I => CLK,
- SIGNAL_O => btnDeBnc
- );
-
- --Registers the debounced button signals, for edge detection.
- btn_reg_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- btnReg <= btnDeBnc(3 downto 0);
- end if;
- end process;
-
- --btnDetect goes high for a single clock cycle when a btn press is
- --detected. This triggers a UART message to begin being sent.
- btnDetect <= '1' when ((btnReg(0)='0' and btnDeBnc(0)='1') or
- (btnReg(1)='0' and btnDeBnc(1)='1') or
- (btnReg(2)='0' and btnDeBnc(2)='1') or
- (btnReg(3)='0' and btnDeBnc(3)='1') ) else
- '0';
-
-
-
-
- ----------------------------------------------------------
- ------ UART Control -------
- ----------------------------------------------------------
- --Messages are sent on reset and when a button is pressed.
-
- --This counter holds the UART state machine in reset for ~2 milliseconds. This
- --will complete transmission of any byte that may have been initiated during
- --FPGA configuration due to the UART_TX line being pulled low, preventing a
- --frame shift error from occuring during the first message.
- process(CLK)
- begin
- if (rising_edge(CLK)) then
- if ((reset_cntr = RESET_CNTR_MAX) or (uartState /= RST_REG)) then
- reset_cntr <= (others=>'0');
- else
- reset_cntr <= reset_cntr + 1;
- end if;
- end if;
- end process;
-
- --Next Uart state logic (states described above)
- next_uartState_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- if (btnDeBnc(4) = '1') then
- uartState <= RST_REG;
- else
- case uartState is
- when RST_REG =>
- if (reset_cntr = RESET_CNTR_MAX) then
- uartState <= LD_INIT_STR;
- end if;
- when LD_INIT_STR =>
- uartState <= SEND_CHAR;
- when SEND_CHAR =>
- uartState <= RDY_LOW;
- when RDY_LOW =>
- uartState <= WAIT_RDY;
- when WAIT_RDY =>
- if (uartRdy = '1') then
- if (strEnd = strIndex) then
- uartState <= WAIT_BTN;
- else
- uartState <= SEND_CHAR;
- end if;
- end if;
- when WAIT_BTN =>
- if (btnDetect = '1') then
- uartState <= LD_BTN_STR;
- end if;
- when LD_BTN_STR =>
- uartState <= SEND_CHAR;
- when others=> --should never be reached
- uartState <= RST_REG;
- end case;
- end if ;
- end if;
- end process;
-
- --Loads the sendStr and strEnd signals when a LD state is
- --is reached.
- string_load_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- if (uartState = LD_INIT_STR) then
- sendStr <= WELCOME_STR;
- strEnd <= WELCOME_STR_LEN;
- elsif (uartState = LD_BTN_STR) then
- sendStr(0 to 23) <= BTN_STR;
- strEnd <= BTN_STR_LEN;
- end if;
- end if;
- end process;
-
- --Conrols the strIndex signal so that it contains the index
- --of the next character that needs to be sent over uart
- char_count_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- if (uartState = LD_INIT_STR or uartState = LD_BTN_STR) then
- strIndex <= 0;
- elsif (uartState = SEND_CHAR) then
- strIndex <= strIndex + 1;
- end if;
- end if;
- end process;
-
- --Controls the UART_TX_CTRL signals
- char_load_process : process (CLK)
- begin
- if (rising_edge(CLK)) then
- if (uartState = SEND_CHAR) then
- uartSend <= '1';
- uartData <= sendStr(strIndex);
- else
- uartSend <= '0';
- end if;
- end if;
- end process;
-
- --Component used to send a byte of data over a UART line.
- Inst_UART_TX_CTRL: UART_TX_CTRL port map(
- SEND => uartSend,
- DATA => uartData,
- CLK => CLK,
- READY => uartRdy,
- UART_TX => uartTX
- );
-
- UART_TXD <= uartTX;
-
-
- ----------------------------------------------------------
- ------ VGA Control -------
- ----------------------------------------------------------
-
- Inst_vga_ctrl: vga_ctrl port map(
- CLK_I => CLK,
- VGA_HS_O => VGA_HS,
- VGA_VS_O => VGA_VS,
- VGA_RED_O => VGA_RED,
- VGA_BLUE_O => VGA_BLUE,
- VGA_GREEN_O => VGA_GREEN,
- PS2_CLK => PS2_CLK,
- PS2_DATA => PS2_DATA
- );
-
- end Behavioral;
|