1 |
5 |
dgisselq |
////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: wbuart.v
|
4 |
|
|
//
|
5 |
|
|
// Project: wbuart32, a full featured UART with simulator
|
6 |
|
|
//
|
7 |
|
|
// Purpose: Unlilke wbuart-insert.v, this is a full blown wishbone core
|
8 |
|
|
// with integrated FIFO support to support the UART transmitter
|
9 |
|
|
// and receiver found within here. As a result, it's usage may be
|
10 |
|
|
// heavier on the bus than the insert, but it may also be more useful.
|
11 |
|
|
//
|
12 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
13 |
|
|
// Gisselquist Technology, LLC
|
14 |
|
|
//
|
15 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
16 |
|
|
//
|
17 |
|
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
18 |
|
|
//
|
19 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
20 |
|
|
// modify it under the terms of the GNU General Public License as published
|
21 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
22 |
|
|
// your option) any later version.
|
23 |
|
|
//
|
24 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
25 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
26 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
27 |
|
|
// for more details.
|
28 |
|
|
//
|
29 |
|
|
// You should have received a copy of the GNU General Public License along
|
30 |
9 |
dgisselq |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no
|
31 |
5 |
dgisselq |
// target there if the PDF file isn't present.) If not, see
|
32 |
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
33 |
|
|
//
|
34 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
35 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
36 |
|
|
//
|
37 |
|
|
//
|
38 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
39 |
|
|
//
|
40 |
|
|
//
|
41 |
17 |
dgisselq |
`default_nettype none
|
42 |
|
|
//
|
43 |
5 |
dgisselq |
`define UART_SETUP 2'b00
|
44 |
|
|
`define UART_FIFO 2'b01
|
45 |
|
|
`define UART_RXREG 2'b10
|
46 |
|
|
`define UART_TXREG 2'b11
|
47 |
|
|
module wbuart(i_clk, i_rst,
|
48 |
|
|
//
|
49 |
|
|
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
|
50 |
9 |
dgisselq |
o_wb_ack, o_wb_stall, o_wb_data,
|
51 |
5 |
dgisselq |
//
|
52 |
15 |
dgisselq |
i_uart_rx, o_uart_tx, i_cts_n, o_rts_n,
|
53 |
5 |
dgisselq |
//
|
54 |
|
|
o_uart_rx_int, o_uart_tx_int,
|
55 |
|
|
o_uart_rxfifo_int, o_uart_txfifo_int);
|
56 |
9 |
dgisselq |
parameter [30:0] INITIAL_SETUP = 31'd25; // 4MB 8N1, when using 100MHz clock
|
57 |
|
|
parameter [3:0] LGFLEN = 4;
|
58 |
|
|
parameter [0:0] HARDWARE_FLOW_CONTROL_PRESENT = 1'b1;
|
59 |
|
|
// Perform a simple/quick bounds check on the log FIFO length, to make
|
60 |
|
|
// sure its within the bounds we can support with our current
|
61 |
|
|
// interface.
|
62 |
|
|
localparam [3:0] LCLLGFLEN = (LGFLEN > 4'ha)? 4'ha
|
63 |
|
|
: ((LGFLEN < 4'h2) ? 4'h2 : LGFLEN);
|
64 |
5 |
dgisselq |
//
|
65 |
17 |
dgisselq |
input wire i_clk, i_rst;
|
66 |
5 |
dgisselq |
// Wishbone inputs
|
67 |
18 |
dgisselq |
input wire i_wb_cyc; // We ignore CYC for efficiency
|
68 |
|
|
input wire i_wb_stb, i_wb_we;
|
69 |
17 |
dgisselq |
input wire [1:0] i_wb_addr;
|
70 |
18 |
dgisselq |
input wire [31:0] i_wb_data; // and only use 30 lines here
|
71 |
9 |
dgisselq |
output reg o_wb_ack;
|
72 |
5 |
dgisselq |
output wire o_wb_stall;
|
73 |
|
|
output reg [31:0] o_wb_data;
|
74 |
|
|
//
|
75 |
17 |
dgisselq |
input wire i_uart_rx;
|
76 |
5 |
dgisselq |
output wire o_uart_tx;
|
77 |
9 |
dgisselq |
// RTS is used for hardware flow control. According to Wikipedia, it
|
78 |
|
|
// should probably be renamed RTR for "ready to receive". It tell us
|
79 |
|
|
// whether or not the receiving hardware is ready to accept another
|
80 |
|
|
// byte. If low, the transmitter will pause.
|
81 |
|
|
//
|
82 |
15 |
dgisselq |
// If you don't wish to use hardware flow control, just set i_cts_n to
|
83 |
|
|
// 1'b0 and let the optimizer simply remove this logic.
|
84 |
17 |
dgisselq |
input wire i_cts_n;
|
85 |
9 |
dgisselq |
// CTS is the "Clear-to-send" signal. We set it anytime our FIFO
|
86 |
|
|
// isn't full. Feel free to ignore this output if you do not wish to
|
87 |
|
|
// use flow control.
|
88 |
15 |
dgisselq |
output reg o_rts_n;
|
89 |
5 |
dgisselq |
output wire o_uart_rx_int, o_uart_tx_int,
|
90 |
|
|
o_uart_rxfifo_int, o_uart_txfifo_int;
|
91 |
|
|
|
92 |
|
|
wire tx_busy;
|
93 |
|
|
|
94 |
|
|
//
|
95 |
|
|
// The UART setup parameters: bits per byte, stop bits, parity, and
|
96 |
|
|
// baud rate are all captured within this uart_setup register.
|
97 |
|
|
//
|
98 |
9 |
dgisselq |
reg [30:0] uart_setup;
|
99 |
18 |
dgisselq |
initial uart_setup = INITIAL_SETUP
|
100 |
|
|
| ((HARDWARE_FLOW_CONTROL_PRESENT==1'b0)? 31'h40000000 : 0);
|
101 |
5 |
dgisselq |
always @(posedge i_clk)
|
102 |
|
|
// Under wishbone rules, a write takes place any time i_wb_stb
|
103 |
|
|
// is high. If that's the case, and if the write was to the
|
104 |
|
|
// setup address, then set us up for the new parameters.
|
105 |
|
|
if ((i_wb_stb)&&(i_wb_addr == `UART_SETUP)&&(i_wb_we))
|
106 |
9 |
dgisselq |
uart_setup <= {
|
107 |
|
|
(i_wb_data[30])
|
108 |
|
|
||(!HARDWARE_FLOW_CONTROL_PRESENT),
|
109 |
|
|
i_wb_data[29:0] };
|
110 |
5 |
dgisselq |
|
111 |
9 |
dgisselq |
/////////////////////////////////////////
|
112 |
5 |
dgisselq |
//
|
113 |
|
|
//
|
114 |
9 |
dgisselq |
// First, the UART receiver
|
115 |
|
|
//
|
116 |
|
|
//
|
117 |
|
|
/////////////////////////////////////////
|
118 |
5 |
dgisselq |
|
119 |
|
|
// First the wires/registers this receiver depends upon
|
120 |
|
|
wire rx_stb, rx_break, rx_perr, rx_ferr, ck_uart;
|
121 |
|
|
wire [7:0] rx_uart_data;
|
122 |
|
|
reg rx_uart_reset;
|
123 |
|
|
|
124 |
|
|
// Here's our UART receiver. Basically, it accepts our setup wires,
|
125 |
|
|
// the UART input, a clock, and a reset line, and produces outputs:
|
126 |
15 |
dgisselq |
// a stb (true when new data is ready), and an 8-bit data out value
|
127 |
|
|
// valid when stb is high.
|
128 |
|
|
`ifdef USE_LITE_UART
|
129 |
|
|
rxuartlite #(INITIAL_SETUP[23:0])
|
130 |
|
|
rx(i_clk, (i_rst), i_uart_rx, rx_stb, rx_uart_data);
|
131 |
|
|
assign rx_break = 1'b0;
|
132 |
|
|
assign rx_perr = 1'b0;
|
133 |
|
|
assign rx_ferr = 1'b0;
|
134 |
|
|
assign ck_uart = 1'b0;
|
135 |
|
|
`else
|
136 |
|
|
// The full receiver also produces a break value (true during a break
|
137 |
|
|
// cond.), and parity/framing error flags--also valid when stb is true.
|
138 |
5 |
dgisselq |
rxuart #(INITIAL_SETUP) rx(i_clk, (i_rst)||(rx_uart_reset),
|
139 |
|
|
uart_setup, i_uart_rx,
|
140 |
|
|
rx_stb, rx_uart_data, rx_break,
|
141 |
|
|
rx_perr, rx_ferr, ck_uart);
|
142 |
15 |
dgisselq |
// The real trick is ... now that we have this extra data, what do we do
|
143 |
5 |
dgisselq |
// with it?
|
144 |
15 |
dgisselq |
`endif
|
145 |
5 |
dgisselq |
|
146 |
|
|
|
147 |
|
|
// We place it into a receiver FIFO.
|
148 |
|
|
//
|
149 |
|
|
// Here's the declarations for the wires it needs.
|
150 |
|
|
wire rx_empty_n, rx_fifo_err;
|
151 |
|
|
wire [7:0] rxf_wb_data;
|
152 |
|
|
wire [15:0] rxf_status;
|
153 |
|
|
reg rxf_wb_read;
|
154 |
|
|
//
|
155 |
|
|
// And here's the FIFO proper.
|
156 |
|
|
//
|
157 |
|
|
// Note that the FIFO will be cleared upon any reset: either if there's
|
158 |
|
|
// a UART break condition on the line, the receiver is in reset, or an
|
159 |
|
|
// external reset is issued.
|
160 |
|
|
//
|
161 |
|
|
// The FIFO accepts strobe and data from the receiver.
|
162 |
|
|
// We issue another wire to it (rxf_wb_read), true when we wish to read
|
163 |
|
|
// from the FIFO, and we get our data in rxf_wb_data. The FIFO outputs
|
164 |
|
|
// four status-type values: 1) is it non-empty, 2) is the FIFO over half
|
165 |
|
|
// full, 3) a 16-bit status register, containing info regarding how full
|
166 |
|
|
// the FIFO truly is, and 4) an error indicator.
|
167 |
9 |
dgisselq |
ufifo #(.LGFLEN(LCLLGFLEN), .RXFIFO(1))
|
168 |
5 |
dgisselq |
rxfifo(i_clk, (i_rst)||(rx_break)||(rx_uart_reset),
|
169 |
|
|
rx_stb, rx_uart_data,
|
170 |
9 |
dgisselq |
rx_empty_n,
|
171 |
5 |
dgisselq |
rxf_wb_read, rxf_wb_data,
|
172 |
|
|
rxf_status, rx_fifo_err);
|
173 |
9 |
dgisselq |
assign o_uart_rxfifo_int = rxf_status[1];
|
174 |
5 |
dgisselq |
|
175 |
|
|
// We produce four interrupts. One of the receive interrupts indicates
|
176 |
|
|
// whether or not the receive FIFO is non-empty. This should wake up
|
177 |
|
|
// the CPU.
|
178 |
9 |
dgisselq |
assign o_uart_rx_int = rxf_status[0];
|
179 |
5 |
dgisselq |
|
180 |
9 |
dgisselq |
// The clear to send line, which may be ignored, but which we set here
|
181 |
|
|
// to be true any time the FIFO has fewer than N-2 items in it.
|
182 |
21 |
dgisselq |
// Why not N-1? Because at N-1 we are totally full, but already so full
|
183 |
9 |
dgisselq |
// that if the transmit end starts sending we won't have a location to
|
184 |
|
|
// receive it. (Transmit might've started on the next character by the
|
185 |
18 |
dgisselq |
// time we set this--thus we need to set it to one, one character before
|
186 |
|
|
// necessary).
|
187 |
|
|
wire [(LCLLGFLEN-1):0] check_cutoff;
|
188 |
|
|
assign check_cutoff = -3;
|
189 |
9 |
dgisselq |
always @(posedge i_clk)
|
190 |
18 |
dgisselq |
o_rts_n <= ((HARDWARE_FLOW_CONTROL_PRESENT)
|
191 |
15 |
dgisselq |
&&(!uart_setup[30])
|
192 |
18 |
dgisselq |
&&(rxf_status[(LCLLGFLEN+1):2] > check_cutoff));
|
193 |
9 |
dgisselq |
|
194 |
5 |
dgisselq |
// If the bus requests that we read from the receive FIFO, we need to
|
195 |
|
|
// tell this to the receive FIFO. Note that because we are using a
|
196 |
|
|
// clock here, the output from the receive FIFO will necessarily be
|
197 |
|
|
// delayed by an extra clock.
|
198 |
|
|
initial rxf_wb_read = 1'b0;
|
199 |
|
|
always @(posedge i_clk)
|
200 |
|
|
rxf_wb_read <= (i_wb_stb)&&(i_wb_addr[1:0]==`UART_RXREG)
|
201 |
|
|
&&(!i_wb_we);
|
202 |
|
|
|
203 |
|
|
// Now, let's deal with those RX UART errors: both the parity and frame
|
204 |
|
|
// errors. As you may recall, these are valid only when rx_stb is
|
205 |
|
|
// valid, so we need to hold on to them until the user reads them via
|
206 |
|
|
// a UART read request..
|
207 |
|
|
reg r_rx_perr, r_rx_ferr;
|
208 |
|
|
initial r_rx_perr = 1'b0;
|
209 |
|
|
initial r_rx_ferr = 1'b0;
|
210 |
|
|
always @(posedge i_clk)
|
211 |
|
|
if ((rx_uart_reset)||(rx_break))
|
212 |
|
|
begin
|
213 |
|
|
// Clear the error
|
214 |
|
|
r_rx_perr <= 1'b0;
|
215 |
|
|
r_rx_ferr <= 1'b0;
|
216 |
|
|
end else if ((i_wb_stb)
|
217 |
|
|
&&(i_wb_addr[1:0]==`UART_RXREG)&&(i_wb_we))
|
218 |
|
|
begin
|
219 |
|
|
// Reset the error lines if a '1' is ever written to
|
220 |
|
|
// them, otherwise leave them alone.
|
221 |
|
|
//
|
222 |
|
|
r_rx_perr <= (r_rx_perr)&&(~i_wb_data[9]);
|
223 |
|
|
r_rx_ferr <= (r_rx_ferr)&&(~i_wb_data[10]);
|
224 |
|
|
end else if (rx_stb)
|
225 |
|
|
begin
|
226 |
|
|
// On an rx_stb, capture any parity or framing error
|
227 |
|
|
// indications. These aren't kept with the data rcvd,
|
228 |
|
|
// but rather kept external to the FIFO. As a result,
|
229 |
|
|
// if you get a parity or framing error, you will never
|
230 |
|
|
// know which data byte it was associated with.
|
231 |
|
|
// For now ... that'll work.
|
232 |
|
|
r_rx_perr <= (r_rx_perr)||(rx_perr);
|
233 |
|
|
r_rx_ferr <= (r_rx_ferr)||(rx_ferr);
|
234 |
|
|
end
|
235 |
|
|
|
236 |
|
|
initial rx_uart_reset = 1'b1;
|
237 |
|
|
always @(posedge i_clk)
|
238 |
|
|
if ((i_rst)||((i_wb_stb)&&(i_wb_addr[1:0]==`UART_SETUP)&&(i_wb_we)))
|
239 |
|
|
// The receiver reset, always set on a master reset
|
240 |
|
|
// request.
|
241 |
|
|
rx_uart_reset <= 1'b1;
|
242 |
|
|
else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_RXREG)&&(i_wb_we))
|
243 |
|
|
// Writes to the receive register will command a receive
|
244 |
|
|
// reset anytime bit[12] is set.
|
245 |
|
|
rx_uart_reset <= i_wb_data[12];
|
246 |
|
|
else
|
247 |
|
|
rx_uart_reset <= 1'b0;
|
248 |
|
|
|
249 |
|
|
// Finally, we'll construct a 32-bit value from these various wires,
|
250 |
|
|
// to be returned over the bus on any read. These include the data
|
251 |
|
|
// that would be read from the FIFO, an error indicator set upon
|
252 |
|
|
// reading from an empty FIFO, a break indicator, and the frame and
|
253 |
|
|
// parity error signals.
|
254 |
|
|
wire [31:0] wb_rx_data;
|
255 |
|
|
assign wb_rx_data = { 16'h00,
|
256 |
|
|
3'h0, rx_fifo_err,
|
257 |
|
|
rx_break, rx_ferr, r_rx_perr, !rx_empty_n,
|
258 |
|
|
rxf_wb_data};
|
259 |
|
|
|
260 |
9 |
dgisselq |
/////////////////////////////////////////
|
261 |
5 |
dgisselq |
//
|
262 |
9 |
dgisselq |
//
|
263 |
5 |
dgisselq |
// Then the UART transmitter
|
264 |
|
|
//
|
265 |
9 |
dgisselq |
//
|
266 |
|
|
/////////////////////////////////////////
|
267 |
15 |
dgisselq |
wire tx_empty_n, txf_err, tx_break;
|
268 |
5 |
dgisselq |
wire [7:0] tx_data;
|
269 |
|
|
wire [15:0] txf_status;
|
270 |
15 |
dgisselq |
reg txf_wb_write, tx_uart_reset;
|
271 |
5 |
dgisselq |
reg [7:0] txf_wb_data;
|
272 |
|
|
|
273 |
|
|
// Unlike the receiver which goes from RXUART -> UFIFO -> WB, the
|
274 |
|
|
// transmitter basically goes WB -> UFIFO -> TXUART. Hence, to build
|
275 |
|
|
// support for the transmitter, we start with the command to write data
|
276 |
|
|
// into the FIFO. In this case, we use the act of writing to the
|
277 |
|
|
// UART_TXREG address as our indication that we wish to write to the
|
278 |
|
|
// FIFO. Here, we create a write command line, and latch the data for
|
279 |
|
|
// the extra clock that it'll take so that the command and data can be
|
280 |
|
|
// both true on the same clock.
|
281 |
|
|
initial txf_wb_write = 1'b0;
|
282 |
|
|
always @(posedge i_clk)
|
283 |
|
|
begin
|
284 |
|
|
txf_wb_write <= (i_wb_stb)&&(i_wb_addr == `UART_TXREG)
|
285 |
|
|
&&(i_wb_we);
|
286 |
|
|
txf_wb_data <= i_wb_data[7:0];
|
287 |
|
|
end
|
288 |
|
|
|
289 |
|
|
// Transmit FIFO
|
290 |
|
|
//
|
291 |
|
|
// Most of this is just wire management. The TX FIFO is identical in
|
292 |
|
|
// implementation to the RX FIFO (theyre both UFIFOs), but the TX
|
293 |
|
|
// FIFO is fed from the WB and read by the transmitter. Some key
|
294 |
|
|
// differences to note: we reset the transmitter on any request for a
|
295 |
|
|
// break. We read from the FIFO any time the UART transmitter is idle.
|
296 |
|
|
// and ... we just set the values (above) for controlling writing into
|
297 |
|
|
// this.
|
298 |
9 |
dgisselq |
ufifo #(.LGFLEN(LGFLEN), .RXFIFO(0))
|
299 |
15 |
dgisselq |
txfifo(i_clk, (tx_break)||(tx_uart_reset),
|
300 |
5 |
dgisselq |
txf_wb_write, txf_wb_data,
|
301 |
9 |
dgisselq |
tx_empty_n,
|
302 |
|
|
(!tx_busy)&&(tx_empty_n), tx_data,
|
303 |
|
|
txf_status, txf_err);
|
304 |
6 |
dgisselq |
// Let's create two transmit based interrupts from the FIFO for the CPU.
|
305 |
9 |
dgisselq |
// The first will be true any time the FIFO has at least one open
|
306 |
|
|
// position within it.
|
307 |
|
|
assign o_uart_tx_int = txf_status[0];
|
308 |
5 |
dgisselq |
// The second will be true any time the FIFO is less than half
|
309 |
|
|
// full, allowing us a change to always keep it (near) fully
|
310 |
|
|
// charged.
|
311 |
9 |
dgisselq |
assign o_uart_txfifo_int = txf_status[1];
|
312 |
5 |
dgisselq |
|
313 |
15 |
dgisselq |
`ifndef USE_LITE_UART
|
314 |
5 |
dgisselq |
// Break logic
|
315 |
|
|
//
|
316 |
|
|
// A break in a UART controller is any time the UART holds the line
|
317 |
|
|
// low for an extended period of time. Here, we capture the wb_data[9]
|
318 |
|
|
// wire, on writes, as an indication we wish to break. As long as you
|
319 |
|
|
// write unsigned characters to the interface, this will never be true
|
320 |
|
|
// unless you wish it to be true. Be aware, though, writing a valid
|
321 |
|
|
// value to the interface will bring it out of the break condition.
|
322 |
15 |
dgisselq |
reg r_tx_break;
|
323 |
5 |
dgisselq |
initial r_tx_break = 1'b0;
|
324 |
|
|
always @(posedge i_clk)
|
325 |
|
|
if (i_rst)
|
326 |
|
|
r_tx_break <= 1'b0;
|
327 |
|
|
else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we))
|
328 |
|
|
r_tx_break <= i_wb_data[9];
|
329 |
15 |
dgisselq |
assign tx_break = r_tx_break;
|
330 |
|
|
`else
|
331 |
|
|
assign tx_break = 1'b0;
|
332 |
|
|
`endif
|
333 |
5 |
dgisselq |
|
334 |
|
|
// TX-Reset logic
|
335 |
|
|
//
|
336 |
|
|
// This is nearly identical to the RX reset logic above. Basically,
|
337 |
|
|
// any time someone writes to bit [12] the transmitter will go through
|
338 |
|
|
// a reset cycle. Keep bit [12] low, and everything will proceed as
|
339 |
|
|
// normal.
|
340 |
|
|
initial tx_uart_reset = 1'b1;
|
341 |
|
|
always @(posedge i_clk)
|
342 |
|
|
if((i_rst)||((i_wb_stb)&&(i_wb_addr == `UART_SETUP)&&(i_wb_we)))
|
343 |
|
|
tx_uart_reset <= 1'b1;
|
344 |
|
|
else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we))
|
345 |
|
|
tx_uart_reset <= i_wb_data[12];
|
346 |
|
|
else
|
347 |
|
|
tx_uart_reset <= 1'b0;
|
348 |
|
|
|
349 |
15 |
dgisselq |
`ifdef USE_LITE_UART
|
350 |
17 |
dgisselq |
txuartlite #(INITIAL_SETUP[23:0]) tx(i_clk, (tx_empty_n), tx_data,
|
351 |
15 |
dgisselq |
o_uart_tx, tx_busy);
|
352 |
|
|
`else
|
353 |
|
|
wire cts_n;
|
354 |
|
|
assign cts_n = (HARDWARE_FLOW_CONTROL_PRESENT)&&(i_cts_n);
|
355 |
5 |
dgisselq |
// Finally, the UART transmitter module itself. Note that we haven't
|
356 |
|
|
// connected the reset wire. Transmitting is as simple as setting
|
357 |
|
|
// the stb value (here set to tx_empty_n) and the data. When these
|
358 |
|
|
// are both set on the same clock that tx_busy is low, the transmitter
|
359 |
|
|
// will move on to the next data byte. Really, the only thing magical
|
360 |
|
|
// here is that tx_empty_n wire--thus, if there's anything in the FIFO,
|
361 |
|
|
// we read it here. (You might notice above, we register a read any
|
362 |
|
|
// time (tx_empty_n) and (!tx_busy) are both true---the condition for
|
363 |
|
|
// starting to transmit a new byte.)
|
364 |
|
|
txuart #(INITIAL_SETUP) tx(i_clk, 1'b0, uart_setup,
|
365 |
|
|
r_tx_break, (tx_empty_n), tx_data,
|
366 |
15 |
dgisselq |
cts_n, o_uart_tx, tx_busy);
|
367 |
|
|
`endif
|
368 |
5 |
dgisselq |
|
369 |
|
|
// Now that we are done with the chain, pick some wires for the user
|
370 |
|
|
// to read on any read of the transmit port.
|
371 |
|
|
//
|
372 |
|
|
// This port is different from reading from the receive port, since
|
373 |
|
|
// there are no side effects. (Reading from the receive port advances
|
374 |
|
|
// the receive FIFO, here only writing to the transmit port advances the
|
375 |
|
|
// transmit FIFO--hence the read values are free for ... whatever.)
|
376 |
|
|
// We choose here to provide information about the transmit FIFO
|
377 |
9 |
dgisselq |
// (txf_err, txf_half_full, txf_full_n), information about the current
|
378 |
5 |
dgisselq |
// voltage on the line (o_uart_tx)--and even the voltage on the receive
|
379 |
|
|
// line (ck_uart), as well as our current setting of the break and
|
380 |
|
|
// whether or not we are actively transmitting.
|
381 |
|
|
wire [31:0] wb_tx_data;
|
382 |
|
|
assign wb_tx_data = { 16'h00,
|
383 |
15 |
dgisselq |
i_cts_n, txf_status[1:0], txf_err,
|
384 |
|
|
ck_uart, o_uart_tx, tx_break, (tx_busy|txf_status[0]),
|
385 |
9 |
dgisselq |
(tx_busy|txf_status[0])?txf_wb_data:8'b00};
|
386 |
5 |
dgisselq |
|
387 |
|
|
// Each of the FIFO's returns a 16 bit status value. This value tells
|
388 |
|
|
// us both how big the FIFO is, as well as how much of the FIFO is in
|
389 |
|
|
// use. Let's merge those two status words together into a word we
|
390 |
|
|
// can use when reading about the FIFO.
|
391 |
|
|
wire [31:0] wb_fifo_data;
|
392 |
|
|
assign wb_fifo_data = { txf_status, rxf_status };
|
393 |
|
|
|
394 |
|
|
// You may recall from above that reads take two clocks. Hence, we
|
395 |
|
|
// need to delay the address decoding for a clock until the data is
|
396 |
|
|
// ready. We do that here.
|
397 |
|
|
reg [1:0] r_wb_addr;
|
398 |
|
|
always @(posedge i_clk)
|
399 |
|
|
r_wb_addr <= i_wb_addr;
|
400 |
|
|
|
401 |
|
|
// Likewise, the acknowledgement is delayed by one clock.
|
402 |
|
|
reg r_wb_ack;
|
403 |
|
|
always @(posedge i_clk) // We'll ACK in two clocks
|
404 |
|
|
r_wb_ack <= i_wb_stb;
|
405 |
|
|
always @(posedge i_clk) // Okay, time to set the ACK
|
406 |
|
|
o_wb_ack <= r_wb_ack;
|
407 |
|
|
|
408 |
|
|
// Finally, set the return data. This data must be valid on the same
|
409 |
|
|
// clock o_wb_ack is high. On all other clocks, it is irrelelant--since
|
410 |
|
|
// no one cares, no one is reading it, it gets lost in the mux in the
|
411 |
|
|
// interconnect, etc. For this reason, we can just simplify our logic.
|
412 |
|
|
always @(posedge i_clk)
|
413 |
|
|
casez(r_wb_addr)
|
414 |
9 |
dgisselq |
`UART_SETUP: o_wb_data <= { 1'b0, uart_setup };
|
415 |
5 |
dgisselq |
`UART_FIFO: o_wb_data <= wb_fifo_data;
|
416 |
|
|
`UART_RXREG: o_wb_data <= wb_rx_data;
|
417 |
|
|
`UART_TXREG: o_wb_data <= wb_tx_data;
|
418 |
|
|
endcase
|
419 |
|
|
|
420 |
|
|
// This device never stalls. Sure, it takes two clocks, but they are
|
421 |
|
|
// pipelined, and nothing stalls that pipeline. (Creates FIFO errors,
|
422 |
|
|
// perhaps, but doesn't stall the pipeline.) Hence, we can just
|
423 |
|
|
// set this value to zero.
|
424 |
|
|
assign o_wb_stall = 1'b0;
|
425 |
|
|
|
426 |
18 |
dgisselq |
// Make verilator happy
|
427 |
|
|
// verilator lint_off UNUSED
|
428 |
|
|
wire [33:0] unused;
|
429 |
|
|
assign unused = { i_rst, i_wb_cyc, i_wb_data };
|
430 |
|
|
// verilator lint_on UNUSED
|
431 |
|
|
|
432 |
5 |
dgisselq |
endmodule
|