OpenCores
URL https://opencores.org/ocsvn/artec_dongle_ii_fpga/artec_dongle_ii_fpga/trunk

Subversion Repositories artec_dongle_ii_fpga

[/] [artec_dongle_ii_fpga/] [trunk/] [src/] [serial_usb/] [serial_usb.vhd] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 nuubik
library ieee;
2
use ieee.std_logic_1164.all;
3
use IEEE.std_logic_unsigned.all;
4
use IEEE.std_logic_arith.all;
5
use work.serial_usb_package.all;
6
use work.dongle_arch.all;
7
 
8
 
9
entity serial_usb is
10
        port(
11
                clock           : in  std_logic;
12
                reset_n         : in  std_logic;
13
                --VCI Port
14
                vci_in          : in vci_slave_in;
15
                vci_out         : out vci_slave_out;
16
                --FTDI fifo interface
17
                uart_ena        : in usbser_ctrl;
18
                fifo_out        : out usb_out;
19
                fifo_in         : in usb_in
20
        );
21
end entity serial_usb;
22
 
23
architecture rtl of serial_usb is
24
 
25
        type reg_type is
26
        record
27
                uart            : uart_registers;
28
                fifo            : usb_out;
29
                fifo_sync: usb_in;
30
                vci             : vci_slave_out;
31
                pc_loop  :  boolean;
32
                vci_write_pending :  boolean;
33
                vci_read_pending :  boolean;
34
                tx_timer :  std_logic_vector(2 downto 0);
35
                rx_timer :  std_logic_vector(2 downto 0);
36
                ftdi_precharge :  std_logic_vector(2 downto 0);  --time between cycles
37
        end record;
38
 
39
        signal reg, reg_in : reg_type;
40
 
41
begin
42
 
43
        -- Design pattern process 1 Implementation 
44
        comb : process (vci_in,uart_ena,reg)
45
                        variable reg_v : reg_type;
46
                begin
47
                        -- Design pattern 
48
                        reg_v:=reg; --pre set default var state
49
 
50
 
51
                        --
52
                        --Debug code send repeating "0123456789" to UART
53
                        --
54
--                      if reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH)='1' then
55
--                              reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH):='0';  --set TX filled
56
--                              reg_v.uart.txhold.reg(3 downto 0):= reg_v.uart.txhold.reg(3 downto 0)+1;
57
--                              if reg_v.uart.txhold.reg(3 downto 0)=x"A" then
58
--                                      reg_v.uart.txhold.reg(3 downto 0):=x"0";
59
--                              end if;
60
--                              reg_v.uart.txhold.reg(7 downto 4):=x"3";
61
--                      end if;
62
 
63
                        ------------------------------------
64
                        ---  <implementation>                   ---
65
                        ------------------------------------
66
 
67
 
68
                        --reduce precharge counter always
69
                        if reg_v.ftdi_precharge>"000" then
70
                                reg_v.ftdi_precharge:=reg_v.ftdi_precharge - 1;
71
                        end if;
72
 
73
                        --VCI write access request                      
74
                        if vci_in.lpc_val='1' and vci_in.lpc_wr='1' and reg_v.vci.lpc_ack='0'  then
75
                                reg_v.vci_write_pending:=true;
76
                        end if;
77
 
78
                        --VCI read access request
79
                        if vci_in.lpc_val='1' and vci_in.lpc_wr='0' and reg_v.vci.lpc_ack='0' then
80
                                reg_v.vci_read_pending:=true;
81
                        end if;
82
 
83
                        --Writable conf registers
84
                        if reg_v.vci_write_pending then --write decode                  
85
                                case vci_in.lpc_addr(2 downto 0) is
86
                                        when "000" =>
87
                                                --select DLAB or not
88
                                                if reg_v.uart.lcr.reg(SEL_LCR_DLAB)='0' then --Line Control Register (LCR) SEL_LCR_DLAB   
89
                                                        reg_v.uart.txhold.reg:=vci_in.lpc_data_o;  --Transmitter Holding Buffer
90
                                                        clr_uart_tx_int(reg_v.uart); --clear tx on tx buff write
91
                                                        if reg_v.uart.mcr.reg(SEL_MCR_LOOP)='0'  then --loop not endabled
92
                                                                reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH):='0'; -- TX not empty
93
                                                                reg_v.uart.lsr.reg(SEL_LSR_EMPTY_DH):='0'; -- TX not empty
94
                                                        else --do local loop
95
                                                                reg_v.uart.rxbuff.reg:=reg_v.uart.txhold.reg;
96
                                                                reg_v.uart.lsr.reg(SEL_LSR_DATARDY):='1'; --set data ready in register
97
                                                                set_uart_rx_int(reg_v.uart);
98
                                                        end if;
99
                                                else
100
                                                        reg_v.uart.div_low.reg:=vci_in.lpc_data_o; --Divisor Latch Low Byte
101
                                                end if;
102
                                        when "001" =>
103
                                                --select DLAB or not
104
                                                if reg_v.uart.lcr.reg(SEL_LCR_DLAB)='0' then --Line Control Register (LCR) SEL_LCR_DLAB   
105
                                                        reg_v.uart.ier.reg:=vci_in.lpc_data_o; --Interrupt Enable Register
106
                                                else
107
                                                        reg_v.uart.div_high.reg:=vci_in.lpc_data_o; --Divisor Latch High Byte
108
                                                end if;
109
                                        when "011" => -- +3
110
                                                reg_v.uart.lcr.reg:=vci_in.lpc_data_o; --Line Control Register (don't care except DLA bit)
111
                                        when "100" => -- +4
112
                                                reg_v.uart.mcr.reg:=vci_in.lpc_data_o; --Modem Control Register (don't care except loopback)
113
                                                reg_v.uart.mcr.reg(SEL_MCR_FLWCTRL):='0'; --this is not supported so auto clear
114
                                        when "111" => -- +7
115
                                                reg_v.uart.scr.reg:=vci_in.lpc_data_o;
116
                                        when others =>
117
                                                null;
118
                                end case;
119
                                --we must ack the write always
120
                                reg_v.vci_write_pending:= false;
121
                                reg_v.vci.lpc_ack:='1'; --ack all writes to non writable addresses for VCI to work
122
                        end if;
123
 
124
                        --Readable conf registers
125
                        if reg_v.vci_read_pending then --write decode                   
126
                                case vci_in.lpc_addr(2 downto 0) is
127
                                        when "000" =>
128
                                                --select DLAB or not
129
                                                if reg_v.uart.lcr.reg(SEL_LCR_DLAB)='0' then --Line Control Register (LCR) SEL_LCR_DLAB   
130
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.rxbuff.reg; --RX read data
131
                                                        reg_v.uart.lsr.reg(SEL_LSR_DATARDY):='0'; --data has been read
132
                                                        clr_uart_rx_int(reg_v.uart);
133
                                                else
134
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.div_low.reg;
135
                                                end if;
136
                                        when "001" =>
137
                                                if reg_v.uart.lcr.reg(SEL_LCR_DLAB)='0' then --Interrupt Enable Register (IER) SEL_LCR_DLAB  
138
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.ier.reg;
139
                                                else --Divisor Latch High Byte
140
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.div_high.reg;
141
                                                end if;
142
                                        when "010" =>
143
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.iir.reg; -- Interrupt Identification Register(IIR)
144
                                                        clr_uart_tx_int(reg_v.uart); --clear tx on iir read
145
                                        when "011" =>
146
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.lcr.reg;
147
                                        when "100" =>
148
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.mcr.reg;
149
                                        when "101" =>
150
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.lsr.reg;
151
                                        when "110" =>
152
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.msr.reg;
153
                                        when "111" =>
154
                                                        reg_v.vci.lpc_data_i:=reg_v.uart.scr.reg;
155
                                        when others =>
156
                                                reg_v.vci.lpc_data_i:=(others=>'0'); -- return 0
157
                                end case;
158
                                --we must ack the read always
159
                                reg_v.vci_read_pending:= false;
160
                                reg_v.vci.lpc_ack:='1'; --ack all reads to non readable addresses for VCI to work                                                                                               
161
                        end if;
162
 
163
                        --UART Register state change handling
164
                        --TX haldler
165
                        if reg_v.fifo.rx_oe_n='1' and reg_v.ftdi_precharge="000" and reg_v.fifo_sync.tx_empty_n='0' and reg_v.tx_timer="000" and reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH)='0' then --No ongoing read and can and has something to TX
166
                                reg_v.fifo.txdata:=reg_v.uart.txhold.reg;
167
                                reg_v.fifo.tx_wr:='1';
168
                                reg_v.tx_timer:="011"; --FDTI fifo timing 40 ns needed for write pulse high
169
                        end if;
170
                        if reg_v.tx_timer>"000" then -- TX cycle timer
171
                                reg_v.tx_timer:=reg_v.tx_timer-1;
172
                                if reg_v.tx_timer="000" then
173
                                        reg_v.fifo.tx_wr:='0'; -- write happens on falling edge '''\,,,
174
                                        reg_v.ftdi_precharge:="011"; --start cycle cap
175
                                        reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH):='1'; -- all sent
176
                                        reg_v.uart.lsr.reg(SEL_LSR_EMPTY_DH):='1'; -- ready for new data
177
                                        set_uart_tx_int(reg_v.uart);
178
                                end if;
179
                        end if;
180
                        --RX Handler
181
 
182
 
183
                        if (not reg_v.pc_loop) or reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH)='1' then
184
                                if reg_v.fifo.tx_wr='0'and reg_v.ftdi_precharge="000" and reg_v.fifo_sync.rx_full_n='0' and reg_v.rx_timer="000" and reg_v.uart.lsr.reg(SEL_LSR_DATARDY)='0' then -- no ongoing TX and data in FTDI fifo and read buffer has been read
185
                                        reg_v.fifo.rx_oe_n:='0'; -- output enable
186
                                        reg_v.rx_timer:="100";
187
                                end if;
188
                                if reg_v.rx_timer>"000" then --RX cycle timer
189
                                        reg_v.rx_timer:=reg_v.rx_timer-1;
190
                                        if reg_v.rx_timer="000" then
191
                                                reg_v.fifo.rx_oe_n:='1'; -- read happens on rising front  ,,,,/'''' of oe_n
192
                                                reg_v.ftdi_precharge:="101"; --start cycle cap
193
                                                reg_v.uart.rxbuff.reg:=reg_v.fifo_sync.rxdata;
194
                                                if reg_v.pc_loop then --pc test loop
195
                                                        reg_v.uart.txhold.reg:=reg_v.fifo_sync.rxdata;
196
                                                        reg_v.uart.lsr.reg(SEL_LSR_EMPTY_TXH):='0'; --do transmit
197
                                                else
198
                                                        reg_v.uart.lsr.reg(SEL_LSR_DATARDY):='1'; --set data ready in register
199
                                                        set_uart_rx_int(reg_v.uart);
200
                                                end if;
201
                                        end if;
202
                                end if;
203
                        end if;
204
 
205
                        --UART Interrupt
206
                        if reg_v.uart.iir.reg(SEL_IIR_PENDING_N)='0' then
207
                                reg_v.vci.lpc_irq:='1'; --set up int signal
208
                        else
209
                                reg_v.vci.lpc_irq:='0';
210
                        end if;
211
                        --End UART
212
 
213
                        --VCI request end, clear ack when val drops                     
214
                        if vci_in.lpc_val='0' and reg_v.vci.lpc_ack='1'  then
215
                                reg_v.vci.lpc_ack:='0';
216
                        end if;
217
 
218
 
219
                        -- Design pattern 
220
                        -- drive register input signals
221
                        reg_in<=reg_v;
222
                        -- drive module outputs signals
223
                        --port_comb_out<= reg_v.port_comb;  --combinatorial output
224
                        --port_reg_out<= reg.port_reg; --registered output
225
                        vci_out<=reg.vci;
226
                        fifo_out<= reg.fifo;
227
                end process;
228
 
229
        -- Pattern process 2, Registers
230
        regs : process (clock,reset_n)
231
                begin
232
                        if reset_n='0' then
233
                                reg.pc_loop<=false;
234
                                reg.rx_timer<=(others=>'0');
235
                                reg.tx_timer<=(others=>'0');
236
                                reg.ftdi_precharge<=(others=>'0');
237
                                reg.vci_read_pending<=false;
238
                                reg.vci_write_pending<=false;
239
                                uart_reset(reg.uart);
240
                                fifo_reset(reg.fifo);
241
                                vci_slave_reset(reg.vci);
242
                        elsif rising_edge(clock) then
243
                                reg<=reg_in;
244
                                reg.fifo_sync<=fifo_in;
245
                        end if;
246
                end process;
247
 
248
 
249
end rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.