1 |
9 |
nuubik |
------------------------------------------------------------------
|
2 |
|
|
-- Universal dongle board source code
|
3 |
|
|
--
|
4 |
|
|
-- Copyright (C) 2006 Artec Design <jyrit@artecdesign.ee>
|
5 |
|
|
--
|
6 |
|
|
-- This source code is free hardware; you can redistribute it and/or
|
7 |
|
|
-- modify it under the terms of the GNU Lesser General Public
|
8 |
|
|
-- License as published by the Free Software Foundation; either
|
9 |
|
|
-- version 2.1 of the License, or (at your option) any later version.
|
10 |
|
|
--
|
11 |
|
|
-- This source code is distributed in the hope that it will be useful,
|
12 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
|
|
-- Lesser General Public License for more details.
|
15 |
|
|
--
|
16 |
|
|
-- You should have received a copy of the GNU Lesser General Public
|
17 |
|
|
-- License along with this library; if not, write to the Free Software
|
18 |
|
|
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
19 |
|
|
--
|
20 |
|
|
--
|
21 |
|
|
-- The complete text of the GNU Lesser General Public License can be found in
|
22 |
|
|
-- the file 'lesser.txt'.
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
----------------------------------------------------------------------------------
|
26 |
|
|
-- Company: Artec Design Ltd
|
27 |
|
|
-- Engineer: Jüri Toomessoo
|
28 |
|
|
--
|
29 |
|
|
-- Create Date: 16:23 23/12/2011
|
30 |
|
|
-- Design Name: UART CPU interface package
|
31 |
|
|
-- Module Name: serial_usb_package
|
32 |
|
|
-- Project Name: FlexyICE
|
33 |
|
|
-- Target Devices:
|
34 |
|
|
-- Tool versions:
|
35 |
|
|
-- Description:
|
36 |
|
|
--
|
37 |
|
|
-- Dependencies:
|
38 |
|
|
--
|
39 |
|
|
-- Revision:
|
40 |
|
|
-- Revision 0.01 - File Created
|
41 |
|
|
-- Additional Comments:
|
42 |
|
|
--
|
43 |
|
|
----------------------------------------------------------------------------------
|
44 |
|
|
library ieee;
|
45 |
|
|
use ieee.std_logic_1164.all;
|
46 |
|
|
use IEEE.std_logic_unsigned.all;
|
47 |
|
|
use IEEE.std_logic_arith.all;
|
48 |
|
|
|
49 |
|
|
package serial_usb_package is
|
50 |
|
|
|
51 |
|
|
type usbser_ctrl is record
|
52 |
|
|
mode_en : std_logic; -- enable this block
|
53 |
|
|
end record;
|
54 |
|
|
|
55 |
|
|
-- USB interface types
|
56 |
|
|
|
57 |
|
|
type usb_out is record
|
58 |
|
|
rx_oe_n : std_logic; -- enables out data if low (next byte detected by edge / in usb chip)
|
59 |
|
|
tx_wr : std_logic; -- write performed on edge \ of signal
|
60 |
|
|
txdata : std_logic_vector(7 downto 0); --bus data
|
61 |
|
|
end record;
|
62 |
|
|
|
63 |
|
|
type usb_in is record
|
64 |
|
|
tx_empty_n : std_logic; -- tx fifo empty (redy for new data if low)
|
65 |
|
|
rx_full_n : std_logic; -- rx fifo empty (data redy if low)
|
66 |
|
|
rxdata : std_logic_vector(7 downto 0); --bus data
|
67 |
|
|
end record;
|
68 |
|
|
|
69 |
|
|
--UART register descriptions
|
70 |
|
|
|
71 |
|
|
|
72 |
|
|
--Interrupt Enable Register (IER)
|
73 |
|
|
constant SEL_IER_RXDATA_INT : natural := 0; --Enable Received Data Available Interrupt
|
74 |
|
|
constant SEL_IER_TXEMPY_INT : natural := 1; --Enable Transmitter Holding Register Empty Interrupt
|
75 |
|
|
constant SEL_IER_RXLINE_INT : natural := 2; --Enable Receiver Line Status Interrupt
|
76 |
|
|
constant SEL_IER_MODEM_INT : natural := 3; --Enable Modem Status Interrupt
|
77 |
|
|
--SEL_IER bit 7 downto 4 --Reserved
|
78 |
|
|
type uart_int_ena is record
|
79 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
80 |
|
|
end record;
|
81 |
|
|
|
82 |
|
|
--Interrupt Identification Register (IIR)
|
83 |
|
|
constant SEL_IIR_PENDING_N : natural := 0; -- No Interrupt Pending when set to '1'
|
84 |
|
|
subtype SEL_IIR_TYPE is natural range 3 downto 1; --
|
85 |
|
|
constant VAL_IIR_TYPE_MODEM : std_logic_vector(2 downto 0) := "000"; -- Modem Status Interrupt
|
86 |
|
|
constant VAL_IIR_TYPE_TXEMPTY : std_logic_vector(2 downto 0) := "001"; -- Transmitter Holding Register Empty Interrupt
|
87 |
|
|
constant VAL_IIR_TYPE_RXDATA : std_logic_vector(2 downto 0) := "010"; -- Received Data Available Interrupt
|
88 |
|
|
constant VAL_IIR_TYPE_RXLINE : std_logic_vector(2 downto 0) := "011"; -- Receiver Line Status Interrupt
|
89 |
|
|
constant SEL_IIR_TYPE_PENDING_N : std_logic_vector(2 downto 0) := "110"; -- 16550 Time-out Interrupt Pending when '1'
|
90 |
|
|
-- SEL_IIR bit 4 -- Reserved
|
91 |
|
|
constant SEL_IIR_TYPE_FIFOENAB_N : natural := 5; -- 64 Byte Fifo Enabled (16750 only)
|
92 |
|
|
subtype SEL_IIR_FIFO is natural range 7 downto 6; -- (16750 only)
|
93 |
|
|
constant VAL_IIR_FIFO_NONE : std_logic_vector(1 downto 0) := "00"; -- No fifo
|
94 |
|
|
constant VAL_IIR_FIFO_UNSTA : std_logic_vector(1 downto 0) := "01"; -- FIFO Enabled but Unusable
|
95 |
|
|
constant VAL_IIR_FIFO_ENAB : std_logic_vector(1 downto 0) := "11"; -- FIFO Enabled
|
96 |
|
|
type uart_int_id is record
|
97 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
98 |
|
|
end record;
|
99 |
|
|
|
100 |
|
|
--(TODO "Implement self clear for bits 1 and 2")
|
101 |
|
|
-- First In / First Out Control Register (FCR) (Write only)
|
102 |
|
|
constant SEL_FCR_FIFO_ENA : natural := 0; -- Enable FIFO's on '1' (data in fifo is lost when set '0')
|
103 |
|
|
constant SEL_FCR_FIFO_RXCLR : natural := 1; -- Clear Receive FIFO on '1' (Self clear bit)
|
104 |
|
|
constant SEL_FCR_FIFO_TXCLR : natural := 2; -- Clear Transmit FIFO '1' (Self clear bit)
|
105 |
|
|
constant SEL_FCR_DMA_MODE : natural := 3; -- DMA Mode Select. Change status of RXRDY & TXRDY pins from mode 1 to mode 2.
|
106 |
|
|
--SEL_FCR bit 4 -- Reserved
|
107 |
|
|
constant SEL_FCR_LARGEFIFO_ENA : natural := 5; -- Enable 64 Byte FIFO (16750 only)
|
108 |
|
|
subtype SEL_FCR_RXINTLEVEL is natural range 7 downto 6; -- Interrupt Trigger Level on RX FIFO
|
109 |
|
|
constant VAL_FCR_RXINTLEVEL_1 : std_logic_vector(1 downto 0) := "00"; -- 1 Byte
|
110 |
|
|
constant VAL_FCR_RXINTLEVEL_4 : std_logic_vector(1 downto 0) := "01"; -- 4 Bytes
|
111 |
|
|
constant VAL_FCR_RXINTLEVEL_8 : std_logic_vector(1 downto 0) := "10"; -- 8 Bytes
|
112 |
|
|
constant VAL_FCR_RXINTLEVEL_14 : std_logic_vector(1 downto 0) := "11"; -- 14 Bytes
|
113 |
|
|
type fifo_ctrl is record
|
114 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
115 |
|
|
end record;
|
116 |
|
|
|
117 |
|
|
--Line Control Register (LCR)
|
118 |
|
|
subtype SEL_LCR_WORDLEN is natural range 1 downto 0; --Word Length
|
119 |
|
|
constant VAL_LCR_WORDLEN_5 : std_logic_vector(1 downto 0) := "00"; -- 5 Bits
|
120 |
|
|
constant VAL_LCR_WORDLEN_6 : std_logic_vector(1 downto 0) := "01"; -- 6 Bits
|
121 |
|
|
constant VAL_LCR_WORDLEN_7 : std_logic_vector(1 downto 0) := "10"; -- 7 Bits
|
122 |
|
|
constant VAL_LCR_WORDLEN_8 : std_logic_vector(1 downto 0) := "11"; -- 8 Bits
|
123 |
|
|
constant SEL_LCR_STOPLEN : natural := 2; -- '0'One Stop Bit ; '1' 2 Stop bits for words of length 6,7 or 8 bits or 1.5 Stop Bits for Word lengths of 5 bits.
|
124 |
|
|
subtype SEL_LCR_PARITY is natural range 5 downto 3; --Parity Select
|
125 |
|
|
constant VAL_LCR_PARITY_ODD : std_logic_vector(2 downto 0) := "001"; -- Odd Parity
|
126 |
|
|
constant VAL_LCR_PARITY_EVEN : std_logic_vector(2 downto 0) := "011"; -- Even Parity
|
127 |
|
|
constant VAL_LCR_PARITY_HIGH : std_logic_vector(2 downto 0) := "101"; -- High Parity (Sticky)
|
128 |
|
|
constant VAL_LCR_PARITY_LOW : std_logic_vector(2 downto 0) := "111"; -- Low Parity (Sticky)
|
129 |
|
|
constant SEL_LCR_BREAKENA : natural := 6; -- Set Break Enable
|
130 |
|
|
constant SEL_LCR_DLAB : natural := 7; -- '1' Divisor Latch Access Bit ; '0' Access to Receiver buffer, Transmitter buffer & Interrupt Enable Register
|
131 |
|
|
type line_ctrl is record
|
132 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
133 |
|
|
end record;
|
134 |
|
|
|
135 |
|
|
-- TODO "Implement Loop back mode"
|
136 |
|
|
--Modem Control Register (MCR)
|
137 |
|
|
constant SEL_MCR_FTERMRDY : natural := 0; -- Force Data Terminal Ready
|
138 |
|
|
constant SEL_MCR_FREQSND : natural := 1; -- Force Request to Send
|
139 |
|
|
constant SEL_MCR_AUX1 : natural := 2; -- Aux Output 1
|
140 |
|
|
constant SEL_MCR_AUX2 : natural := 3; -- Aux Output 2
|
141 |
|
|
constant SEL_MCR_LOOP : natural := 4; -- LoopBack Mode
|
142 |
|
|
constant SEL_MCR_FLWCTRL : natural := 5; -- Autoflow Control Enabled (16750 only)
|
143 |
|
|
type modem_ctrl is record
|
144 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
145 |
|
|
end record;
|
146 |
|
|
|
147 |
|
|
--Line Status Register (LSR) (read only)
|
148 |
|
|
constant SEL_LSR_DATARDY : natural := 0; -- Data Ready TODO "Implement data ready"
|
149 |
|
|
constant SEL_LSR_OVRERR : natural := 1; -- Overrun Error (input reg over flow) TODO "Implement over run"
|
150 |
|
|
constant SEL_LSR_PARERR : natural := 2; -- Parity Error
|
151 |
|
|
constant SEL_LSR_FRMERR : natural := 3; -- Framing Error
|
152 |
|
|
constant SEL_LSR_BREAKINT : natural := 4; -- Break Interrupt
|
153 |
|
|
constant SEL_LSR_EMPTY_TXH : natural := 5; -- Empty Transmitter Holding Register
|
154 |
|
|
constant SEL_LSR_EMPTY_DH : natural := 6; -- Empty Data Holding Registers
|
155 |
|
|
constant SEL_LSR_RXFIFOERR : natural := 7; -- Error in Received FIFO
|
156 |
|
|
type line_status is record
|
157 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
158 |
|
|
end record;
|
159 |
|
|
|
160 |
|
|
--Modem Status Register (MSR)
|
161 |
|
|
constant SEL_MSR_CHN_CTS : natural := 0; -- Delta Clear to Send (auto falloff on reg read)
|
162 |
|
|
constant SEL_MSR_CHN_RDY : natural := 1; -- Delta Data Set Ready (auto falloff on reg read)
|
163 |
|
|
constant SEL_MSR_CHN_RING : natural := 2; -- Trailing Edge Ring Indicator (auto falloff on reg read)
|
164 |
|
|
constant SEL_MSR_CHN_CD : natural := 3; -- Delta Data Carrier Detect (auto falloff on reg read)
|
165 |
|
|
constant SEL_MSR_CTC : natural := 4; -- Clear To Send (signal state)
|
166 |
|
|
constant SEL_MSR_RDY : natural := 5; -- Data Set Ready (signal state)
|
167 |
|
|
constant SEL_MSR_RING : natural := 6; -- Ring Indicator (signal state)
|
168 |
|
|
constant SEL_MSR_CD : natural := 7; -- Carrier Detect (signal state)
|
169 |
|
|
type modem_status is record
|
170 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
171 |
|
|
end record;
|
172 |
|
|
|
173 |
|
|
-- Scratch Register
|
174 |
|
|
type scratch is record
|
175 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
176 |
|
|
end record;
|
177 |
|
|
|
178 |
|
|
type general_reg is record
|
179 |
|
|
reg : std_logic_vector(7 downto 0); --Register
|
180 |
|
|
end record;
|
181 |
|
|
|
182 |
|
|
type uart_registers is record
|
183 |
|
|
txhold : general_reg; --Register (Write) (OFS +0 DLAB=0) --Transmitter Holding Buffer
|
184 |
|
|
rxbuff : general_reg; --Register (Read) (OFS +0 DLAB=0) --Receiver Buffer
|
185 |
|
|
div_low : general_reg; --Register (R/W) (OFS +0 DLAB=1) --Divisor Latch Low Byte
|
186 |
|
|
ier : uart_int_ena; --Register (R/W) (OFS +1 DLAB=0) --Interrupt Enable Register
|
187 |
|
|
div_high : general_reg; --Register (R/W) (OFS +1 DLAB=1) --Divisor Latch High Byte
|
188 |
|
|
iir : uart_int_id; --Register (Read) (OFS +2 DLAB=-) --Interrupt Identification Register
|
189 |
|
|
fcr : fifo_ctrl; --Register (Write) (OFS +2 DLAB=-) --FIFO Control Register
|
190 |
|
|
lcr : line_ctrl; --Register (R/W) (OFS +3 DLAB=-) --Line Control Register
|
191 |
|
|
mcr : modem_ctrl; --Register (R/W) (OFS +4 DLAB=-) --Modem Control Register
|
192 |
|
|
lsr : line_status; --Register (Read) (OFS +5 DLAB=-) --Line Status Register
|
193 |
|
|
msr : modem_status; --Register (Read) (OFS +6 DLAB=-) --Modem Status Register
|
194 |
|
|
scr : scratch; --Register (R/W) (OFS +7 DLAB=-) --Scratch Register
|
195 |
|
|
end record;
|
196 |
|
|
|
197 |
|
|
procedure uart_reset(signal uart : out uart_registers);
|
198 |
|
|
procedure fifo_reset(signal fifo : out usb_out);
|
199 |
|
|
|
200 |
|
|
procedure set_uart_rx_int(variable uart : inout uart_registers);
|
201 |
|
|
procedure clr_uart_rx_int(variable uart : inout uart_registers);
|
202 |
|
|
|
203 |
|
|
procedure set_uart_tx_int(variable uart : inout uart_registers);
|
204 |
|
|
procedure clr_uart_tx_int(variable uart : inout uart_registers);
|
205 |
|
|
|
206 |
|
|
|
207 |
|
|
end package serial_usb_package;
|
208 |
|
|
package body serial_usb_package is
|
209 |
|
|
|
210 |
|
|
procedure fifo_reset(
|
211 |
|
|
signal fifo : out usb_out) is
|
212 |
|
|
variable f : usb_out;
|
213 |
|
|
begin
|
214 |
|
|
f.rx_oe_n:='1';
|
215 |
|
|
f.tx_wr:='0';
|
216 |
|
|
f.txdata:=(others=>'0');
|
217 |
|
|
fifo<=f;
|
218 |
|
|
end procedure fifo_reset;
|
219 |
|
|
|
220 |
|
|
procedure uart_reset(
|
221 |
|
|
signal uart : out uart_registers) is
|
222 |
|
|
variable u : uart_registers;
|
223 |
|
|
begin
|
224 |
|
|
u.txhold.reg := x"00"; --not needed direct write possible
|
225 |
|
|
u.rxbuff.reg := x"00";
|
226 |
|
|
u.div_low.reg := x"00";
|
227 |
|
|
u.ier.reg := x"00";
|
228 |
|
|
u.div_high.reg := x"01"; -- 115200 baud
|
229 |
|
|
u.iir.reg := x"41"; --no int pending, fifo enabled but unusable
|
230 |
|
|
u.fcr.reg := x"00"; --
|
231 |
|
|
u.lcr.reg := x"03"; -- set 8 bit data 1 stop no parity DLA 0
|
232 |
|
|
u.mcr.reg := x"00"; --
|
233 |
|
|
u.lsr.reg := x"60"; -- tx empty and rx empty flags set on reset
|
234 |
|
|
u.msr.reg := x"10"; -- Clear To Send is high after reset
|
235 |
|
|
u.scr.reg := x"00"; --
|
236 |
|
|
uart <= u;
|
237 |
|
|
end procedure uart_reset;
|
238 |
|
|
|
239 |
|
|
|
240 |
|
|
procedure set_uart_rx_int(variable uart : inout uart_registers) is
|
241 |
|
|
begin
|
242 |
|
|
if uart.ier.reg(SEL_IER_RXDATA_INT)='1' then --int enabled
|
243 |
|
|
uart.iir.reg(SEL_IIR_TYPE):=VAL_IIR_TYPE_RXDATA;
|
244 |
|
|
uart.iir.reg(SEL_IIR_PENDING_N):='0'; --set int pending
|
245 |
|
|
end if;
|
246 |
|
|
end procedure set_uart_rx_int;
|
247 |
|
|
|
248 |
|
|
procedure clr_uart_rx_int(variable uart : inout uart_registers) is
|
249 |
|
|
begin
|
250 |
|
|
if uart.iir.reg(SEL_IIR_TYPE)=VAL_IIR_TYPE_RXDATA and uart.iir.reg(SEL_IIR_PENDING_N)='0' then --suitable int
|
251 |
|
|
uart.iir.reg(SEL_IIR_PENDING_N):='1'; --clear int pending
|
252 |
|
|
end if;
|
253 |
|
|
end procedure clr_uart_rx_int;
|
254 |
|
|
|
255 |
|
|
|
256 |
|
|
procedure set_uart_tx_int(variable uart : inout uart_registers) is
|
257 |
|
|
begin
|
258 |
|
|
if uart.ier.reg(SEL_IER_TXEMPY_INT)='1' then --int enabled
|
259 |
|
|
uart.iir.reg(SEL_IIR_TYPE):=VAL_IIR_TYPE_TXEMPTY;
|
260 |
|
|
uart.iir.reg(SEL_IIR_PENDING_N):='0'; --set int pending
|
261 |
|
|
end if;
|
262 |
|
|
end procedure set_uart_tx_int;
|
263 |
|
|
|
264 |
|
|
procedure clr_uart_tx_int(variable uart : inout uart_registers) is
|
265 |
|
|
begin
|
266 |
|
|
if uart.iir.reg(SEL_IIR_TYPE)=VAL_IIR_TYPE_TXEMPTY and uart.iir.reg(SEL_IIR_PENDING_N)='0' then --suitable int
|
267 |
|
|
uart.iir.reg(SEL_IIR_PENDING_N):='1'; --clear int pending
|
268 |
|
|
end if;
|
269 |
|
|
end procedure clr_uart_tx_int;
|
270 |
|
|
|
271 |
|
|
end package body serial_usb_package;
|