No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GPIO_Demo.vhd 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. ----------------------------------------------------------------------------
  2. -- GPIO_Demo.vhd -- Basys3 GPIO/UART Demonstration Project
  3. ----------------------------------------------------------------------------
  4. -- Author: Marshall Wingerson Adapted from Sam Bobrowicz
  5. -- Copyright 2013 Digilent, Inc.
  6. ----------------------------------------------------------------------------
  7. --
  8. ----------------------------------------------------------------------------
  9. -- The GPIO/UART Demo project demonstrates a simple usage of the Basys3's
  10. -- GPIO and UART. The behavior is as follows:
  11. --
  12. -- *The 16 User LEDs are tied to the 16 User Switches. While the center
  13. -- User button is pressed, the LEDs are instead tied to GND
  14. -- *The 7-Segment display counts from 0 to 9 on each of its 8
  15. -- digits. This count is reset when the center button is pressed.
  16. -- Also, single anodes of the 7-Segment display are blanked by
  17. -- holding BTNU, BTNL, BTND, or BTNR. Holding the center button
  18. -- blanks all the 7-Segment anodes.
  19. -- *An introduction message is sent across the UART when the device
  20. -- is finished being configured, and after the center User button
  21. -- is pressed.
  22. -- *A message is sent over UART whenever BTNU, BTNL, BTND, or BTNR is
  23. -- pressed.
  24. -- *Note that the center user button behaves as a user reset button
  25. -- and is referred to as such in the code comments below
  26. -- *A test pattern is displayed on the VGA port at 1280x1024 resolution.
  27. -- If a mouse is attached to the USB-HID port, a cursor can be moved
  28. -- around the pattern.
  29. --
  30. -- All UART communication can be captured by attaching the UART port to a
  31. -- computer running a Terminal program with 9600 Baud Rate, 8 data bits, no
  32. -- parity, and 1 stop bit.
  33. ----------------------------------------------------------------------------
  34. --
  35. ----------------------------------------------------------------------------
  36. -- Revision History:
  37. -- 08/08/2011(SamB): Created using Xilinx Tools 13.2
  38. -- 08/27/2013(MarshallW): Modified for the Nexys4 with Xilinx ISE 14.4\
  39. -- --added RGB and microphone
  40. -- 7/22/2014(SamB): Modified for the Basys3 with Vivado 2014.2\
  41. -- --Removed RGB and microphone
  42. ----------------------------------------------------------------------------
  43. library IEEE;
  44. use IEEE.STD_LOGIC_1164.ALL;
  45. --The IEEE.std_logic_unsigned contains definitions that allow
  46. --std_logic_vector types to be used with the + operator to instantiate a
  47. --counter.
  48. use IEEE.std_logic_unsigned.all;
  49. entity GPIO_demo is
  50. Port ( SW : in STD_LOGIC_VECTOR (15 downto 0);
  51. BTN : in STD_LOGIC_VECTOR (4 downto 0);
  52. CLK : in STD_LOGIC;
  53. LED : out STD_LOGIC_VECTOR (15 downto 0);
  54. SSEG_CA : out STD_LOGIC_VECTOR (7 downto 0);
  55. SSEG_AN : out STD_LOGIC_VECTOR (3 downto 0);
  56. UART_TXD : out STD_LOGIC;
  57. VGA_RED : out STD_LOGIC_VECTOR (3 downto 0);
  58. VGA_BLUE : out STD_LOGIC_VECTOR (3 downto 0);
  59. VGA_GREEN : out STD_LOGIC_VECTOR (3 downto 0);
  60. VGA_VS : out STD_LOGIC;
  61. VGA_HS : out STD_LOGIC;
  62. PS2_CLK : inout STD_LOGIC;
  63. PS2_DATA : inout STD_LOGIC
  64. );
  65. end GPIO_demo;
  66. architecture Behavioral of GPIO_demo is
  67. component UART_TX_CTRL
  68. Port(
  69. SEND : in std_logic;
  70. DATA : in std_logic_vector(7 downto 0);
  71. CLK : in std_logic;
  72. READY : out std_logic;
  73. UART_TX : out std_logic
  74. );
  75. end component;
  76. component debouncer
  77. Generic(
  78. DEBNC_CLOCKS : integer;
  79. PORT_WIDTH : integer);
  80. Port(
  81. SIGNAL_I : in std_logic_vector(4 downto 0);
  82. CLK_I : in std_logic;
  83. SIGNAL_O : out std_logic_vector(4 downto 0)
  84. );
  85. end component;
  86. component vga_ctrl
  87. Port ( CLK_I : in STD_LOGIC;
  88. VGA_HS_O : out STD_LOGIC;
  89. VGA_VS_O : out STD_LOGIC;
  90. VGA_RED_O : out STD_LOGIC_VECTOR (3 downto 0);
  91. VGA_BLUE_O : out STD_LOGIC_VECTOR (3 downto 0);
  92. VGA_GREEN_O : out STD_LOGIC_VECTOR (3 downto 0);
  93. PS2_CLK : inout STD_LOGIC;
  94. PS2_DATA : inout STD_LOGIC
  95. );
  96. end component;
  97. --The type definition for the UART state machine type. Here is a description of what
  98. --occurs during each state:
  99. -- RST_REG -- Do Nothing. This state is entered after configuration or a user reset.
  100. -- The state is set to LD_INIT_STR.
  101. -- LD_INIT_STR -- The Welcome String is loaded into the sendStr variable and the strIndex
  102. -- variable is set to zero. The welcome string length is stored in the StrEnd
  103. -- variable. The state is set to SEND_CHAR.
  104. -- SEND_CHAR -- uartSend is set high for a single clock cycle, signaling the character
  105. -- data at sendStr(strIndex) to be registered by the UART_TX_CTRL at the next
  106. -- cycle. Also, strIndex is incremented (behaves as if it were post
  107. -- incremented after reading the sendStr data). The state is set to RDY_LOW.
  108. -- RDY_LOW -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go low,
  109. -- indicating a send operation has begun. State is set to WAIT_RDY.
  110. -- WAIT_RDY -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go high,
  111. -- indicating a send operation has finished. If READY is high and strEnd =
  112. -- StrIndex then state is set to WAIT_BTN, else if READY is high and strEnd /=
  113. -- StrIndex then state is set to SEND_CHAR.
  114. -- WAIT_BTN -- Do nothing. Wait for a button press on BTNU, BTNL, BTND, or BTNR. If a
  115. -- button press is detected, set the state to LD_BTN_STR.
  116. -- LD_BTN_STR -- The Button String is loaded into the sendStr variable and the strIndex
  117. -- variable is set to zero. The button string length is stored in the StrEnd
  118. -- variable. The state is set to SEND_CHAR.
  119. type UART_STATE_TYPE is (RST_REG, LD_INIT_STR, SEND_CHAR, RDY_LOW, WAIT_RDY, WAIT_BTN, LD_BTN_STR);
  120. --The CHAR_ARRAY type is a variable length array of 8 bit std_logic_vectors.
  121. --Each std_logic_vector contains an ASCII value and represents a character in
  122. --a string. The character at index 0 is meant to represent the first
  123. --character of the string, the character at index 1 is meant to represent the
  124. --second character of the string, and so on.
  125. type CHAR_ARRAY is array (integer range<>) of std_logic_vector(7 downto 0);
  126. constant TMR_CNTR_MAX : std_logic_vector(26 downto 0) := "101111101011110000100000000"; --100,000,000 = clk cycles per second
  127. constant TMR_VAL_MAX : std_logic_vector(3 downto 0) := "1001"; --9
  128. constant RESET_CNTR_MAX : std_logic_vector(17 downto 0) := "110000110101000000";-- 100,000,000 * 0.002 = 200,000 = clk cycles per 2 ms
  129. constant MAX_STR_LEN : integer := 27;
  130. constant WELCOME_STR_LEN : natural := 27;
  131. constant BTN_STR_LEN : natural := 24;
  132. --Welcome string definition. Note that the values stored at each index
  133. --are the ASCII values of the indicated character.
  134. constant WELCOME_STR : CHAR_ARRAY(0 to 26) := (X"0A", --\n
  135. X"0D", --\r
  136. X"42", --B
  137. X"41", --A
  138. X"53", --S
  139. X"59", --Y
  140. X"53", --S
  141. X"33", --3
  142. X"20", --
  143. X"47", --G
  144. X"50", --P
  145. X"49", --I
  146. X"4F", --O
  147. X"2F", --/
  148. X"55", --U
  149. X"41", --A
  150. X"52", --R
  151. X"54", --T
  152. X"20", --
  153. X"44", --D
  154. X"45", --E
  155. X"4D", --M
  156. X"4F", --O
  157. X"21", --!
  158. X"0A", --\n
  159. X"0A", --\n
  160. X"0D"); --\r
  161. --Button press string definition.
  162. constant BTN_STR : CHAR_ARRAY(0 to 23) := (X"42", --B
  163. X"75", --u
  164. X"74", --t
  165. X"74", --t
  166. X"6F", --o
  167. X"6E", --n
  168. X"20", --
  169. X"70", --p
  170. X"72", --r
  171. X"65", --e
  172. X"73", --s
  173. X"73", --s
  174. X"20", --
  175. X"64", --d
  176. X"65", --e
  177. X"74", --t
  178. X"65", --e
  179. X"63", --c
  180. X"74", --t
  181. X"65", --e
  182. X"64", --d
  183. X"21", --!
  184. X"0A", --\n
  185. X"0D"); --\r
  186. --This is used to determine when the 7-segment display should be
  187. --incremented
  188. signal tmrCntr : std_logic_vector(26 downto 0) := (others => '0');
  189. --This counter keeps track of which number is currently being displayed
  190. --on the 7-segment.
  191. signal tmrVal : std_logic_vector(3 downto 0) := (others => '0');
  192. --Contains the current string being sent over uart.
  193. signal sendStr : CHAR_ARRAY(0 to (MAX_STR_LEN - 1));
  194. --Contains the length of the current string being sent over uart.
  195. signal strEnd : natural;
  196. --Contains the index of the next character to be sent over uart
  197. --within the sendStr variable.
  198. signal strIndex : natural;
  199. --Used to determine when a button press has occured
  200. signal btnReg : std_logic_vector (3 downto 0) := "0000";
  201. signal btnDetect : std_logic;
  202. --UART_TX_CTRL control signals
  203. signal uartRdy : std_logic;
  204. signal uartSend : std_logic := '0';
  205. signal uartData : std_logic_vector (7 downto 0):= "00000000";
  206. signal uartTX : std_logic;
  207. --Current uart state signal
  208. signal uartState : UART_STATE_TYPE := RST_REG;
  209. --Debounced btn signals used to prevent single button presses
  210. --from being interpreted as multiple button presses.
  211. signal btnDeBnc : std_logic_vector(4 downto 0);
  212. signal clk_cntr_reg : std_logic_vector (4 downto 0) := (others=>'0');
  213. signal pwm_val_reg : std_logic := '0';
  214. --this counter counts the amount of time paused in the UART reset state
  215. signal reset_cntr : std_logic_vector (17 downto 0) := (others=>'0');
  216. begin
  217. ----------------------------------------------------------
  218. ------ LED Control -------
  219. ----------------------------------------------------------
  220. with BTN(4) select
  221. LED <= SW when '0',
  222. "0000000000000000" when others;
  223. ----------------------------------------------------------
  224. ------ 7-Seg Display Control -------
  225. ----------------------------------------------------------
  226. --Digits are incremented every second, and are blanked in
  227. --response to button presses.
  228. --Individual and reset blanking of Anodes
  229. with BTN(4) select
  230. SSEG_AN(3 downto 0) <= btnDeBnc(3 downto 0) when '0',
  231. "1111" when others;
  232. --This process controls the counter that triggers the 7-segment
  233. --to be incremented. It counts 100,000,000 and then resets.
  234. timer_counter_process : process (CLK)
  235. begin
  236. if (rising_edge(CLK)) then
  237. if ((tmrCntr = TMR_CNTR_MAX) or (BTN(4) = '1')) then
  238. tmrCntr <= (others => '0');
  239. else
  240. tmrCntr <= tmrCntr + 1;
  241. end if;
  242. end if;
  243. end process;
  244. --This process increments the digit being displayed on the
  245. --7-segment display every second.
  246. timer_inc_process : process (CLK)
  247. begin
  248. if (rising_edge(CLK)) then
  249. if (BTN(4) = '1') then
  250. tmrVal <= (others => '0');
  251. elsif (tmrCntr = TMR_CNTR_MAX) then
  252. if (tmrVal = TMR_VAL_MAX) then
  253. tmrVal <= (others => '0');
  254. else
  255. tmrVal <= tmrVal + 1;
  256. end if;
  257. end if;
  258. end if;
  259. end process;
  260. --This select statement encodes the value of tmrVal to the necessary
  261. --cathode signals to display it on the 7-segment
  262. with tmrVal select
  263. SSEG_CA <= "01000000" when "0000",
  264. "01111001" when "0001",
  265. "00100100" when "0010",
  266. "00110000" when "0011",
  267. "00011001" when "0100",
  268. "00010010" when "0101",
  269. "00000010" when "0110",
  270. "01111000" when "0111",
  271. "00000000" when "1000",
  272. "00010000" when "1001",
  273. "11111111" when others;
  274. ----------------------------------------------------------
  275. ------ Button Control -------
  276. ----------------------------------------------------------
  277. --Buttons are debounced and their rising edges are detected
  278. --to trigger UART messages
  279. --Debounces btn signals
  280. Inst_btn_debounce: debouncer
  281. generic map(
  282. DEBNC_CLOCKS => (2**16),
  283. PORT_WIDTH => 5)
  284. port map(
  285. SIGNAL_I => BTN,
  286. CLK_I => CLK,
  287. SIGNAL_O => btnDeBnc
  288. );
  289. --Registers the debounced button signals, for edge detection.
  290. btn_reg_process : process (CLK)
  291. begin
  292. if (rising_edge(CLK)) then
  293. btnReg <= btnDeBnc(3 downto 0);
  294. end if;
  295. end process;
  296. --btnDetect goes high for a single clock cycle when a btn press is
  297. --detected. This triggers a UART message to begin being sent.
  298. btnDetect <= '1' when ((btnReg(0)='0' and btnDeBnc(0)='1') or
  299. (btnReg(1)='0' and btnDeBnc(1)='1') or
  300. (btnReg(2)='0' and btnDeBnc(2)='1') or
  301. (btnReg(3)='0' and btnDeBnc(3)='1') ) else
  302. '0';
  303. ----------------------------------------------------------
  304. ------ UART Control -------
  305. ----------------------------------------------------------
  306. --Messages are sent on reset and when a button is pressed.
  307. --This counter holds the UART state machine in reset for ~2 milliseconds. This
  308. --will complete transmission of any byte that may have been initiated during
  309. --FPGA configuration due to the UART_TX line being pulled low, preventing a
  310. --frame shift error from occuring during the first message.
  311. process(CLK)
  312. begin
  313. if (rising_edge(CLK)) then
  314. if ((reset_cntr = RESET_CNTR_MAX) or (uartState /= RST_REG)) then
  315. reset_cntr <= (others=>'0');
  316. else
  317. reset_cntr <= reset_cntr + 1;
  318. end if;
  319. end if;
  320. end process;
  321. --Next Uart state logic (states described above)
  322. next_uartState_process : process (CLK)
  323. begin
  324. if (rising_edge(CLK)) then
  325. if (btnDeBnc(4) = '1') then
  326. uartState <= RST_REG;
  327. else
  328. case uartState is
  329. when RST_REG =>
  330. if (reset_cntr = RESET_CNTR_MAX) then
  331. uartState <= LD_INIT_STR;
  332. end if;
  333. when LD_INIT_STR =>
  334. uartState <= SEND_CHAR;
  335. when SEND_CHAR =>
  336. uartState <= RDY_LOW;
  337. when RDY_LOW =>
  338. uartState <= WAIT_RDY;
  339. when WAIT_RDY =>
  340. if (uartRdy = '1') then
  341. if (strEnd = strIndex) then
  342. uartState <= WAIT_BTN;
  343. else
  344. uartState <= SEND_CHAR;
  345. end if;
  346. end if;
  347. when WAIT_BTN =>
  348. if (btnDetect = '1') then
  349. uartState <= LD_BTN_STR;
  350. end if;
  351. when LD_BTN_STR =>
  352. uartState <= SEND_CHAR;
  353. when others=> --should never be reached
  354. uartState <= RST_REG;
  355. end case;
  356. end if ;
  357. end if;
  358. end process;
  359. --Loads the sendStr and strEnd signals when a LD state is
  360. --is reached.
  361. string_load_process : process (CLK)
  362. begin
  363. if (rising_edge(CLK)) then
  364. if (uartState = LD_INIT_STR) then
  365. sendStr <= WELCOME_STR;
  366. strEnd <= WELCOME_STR_LEN;
  367. elsif (uartState = LD_BTN_STR) then
  368. sendStr(0 to 23) <= BTN_STR;
  369. strEnd <= BTN_STR_LEN;
  370. end if;
  371. end if;
  372. end process;
  373. --Conrols the strIndex signal so that it contains the index
  374. --of the next character that needs to be sent over uart
  375. char_count_process : process (CLK)
  376. begin
  377. if (rising_edge(CLK)) then
  378. if (uartState = LD_INIT_STR or uartState = LD_BTN_STR) then
  379. strIndex <= 0;
  380. elsif (uartState = SEND_CHAR) then
  381. strIndex <= strIndex + 1;
  382. end if;
  383. end if;
  384. end process;
  385. --Controls the UART_TX_CTRL signals
  386. char_load_process : process (CLK)
  387. begin
  388. if (rising_edge(CLK)) then
  389. if (uartState = SEND_CHAR) then
  390. uartSend <= '1';
  391. uartData <= sendStr(strIndex);
  392. else
  393. uartSend <= '0';
  394. end if;
  395. end if;
  396. end process;
  397. --Component used to send a byte of data over a UART line.
  398. Inst_UART_TX_CTRL: UART_TX_CTRL port map(
  399. SEND => uartSend,
  400. DATA => uartData,
  401. CLK => CLK,
  402. READY => uartRdy,
  403. UART_TX => uartTX
  404. );
  405. UART_TXD <= uartTX;
  406. ----------------------------------------------------------
  407. ------ VGA Control -------
  408. ----------------------------------------------------------
  409. Inst_vga_ctrl: vga_ctrl port map(
  410. CLK_I => CLK,
  411. VGA_HS_O => VGA_HS,
  412. VGA_VS_O => VGA_VS,
  413. VGA_RED_O => VGA_RED,
  414. VGA_BLUE_O => VGA_BLUE,
  415. VGA_GREEN_O => VGA_GREEN,
  416. PS2_CLK => PS2_CLK,
  417. PS2_DATA => PS2_DATA
  418. );
  419. end Behavioral;