URL
https://opencores.org/ocsvn/wbuart32/wbuart32/trunk
Subversion Repositories wbuart32
Compare Revisions
- This comparison shows the changes necessary to convert path
/wbuart32/trunk/rtl
- from Rev 7 to Rev 9
- ↔ Reverse comparison
Rev 7 → Rev 9
/rxuart.v
19,9 → 19,13
// Now for the setup register. The register is 32 bits, so that this |
// UART may be set up over a 32-bit bus. |
// |
// i_setup[30] True if we are using hardware flow control. This bit |
// is ignored within this module, as any receive hardware flow |
// control will need to be implemented elsewhere. |
// |
// i_setup[29:28] Indicates the number of data bits per word. This will |
// either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10 |
// for a six bit word, or 2'b11 for a five bit word. |
// either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10 |
// for a six bit word, or 2'b11 for a five bit word. |
// |
// i_setup[27] Indicates whether or not to use one or two stop bits. |
// Set this to one to expect two stop bits, zero for one. |
74,7 → 78,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
90,7 → 94,7
// ..7 Bits arrive |
// 8 Stop bit (x1) |
// 9 Stop bit (x2) |
/// c break condition |
// c break condition |
// d Waiting for the channel to go high |
// e Waiting for the reset to complete |
// f Idle state |
113,10 → 117,10
|
module rxuart(i_clk, i_reset, i_setup, i_uart_rx, o_wr, o_data, o_break, |
o_parity_err, o_frame_err, o_ck_uart); |
parameter INITIAL_SETUP = 30'd868; |
parameter [30:0] INITIAL_SETUP = 31'd868; |
// 8 data bits, no parity, (at least 1) stop bit |
input i_clk, i_reset; |
input [29:0] i_setup; |
input [30:0] i_setup; |
input i_uart_rx; |
output reg o_wr; |
output reg [7:0] o_data; |
132,6 → 136,7
reg [3:0] state; |
|
assign clocks_per_baud = { 4'h0, r_setup[23:0] }; |
// assign hw_flow_control = !r_setup[30]; |
assign data_bits = r_setup[29:28]; |
assign dblstop = r_setup[27]; |
assign use_parity = r_setup[26]; |
214,10 → 219,10
|
// Allow our controlling processor to change our setup at any time |
// outside of receiving/processing a character. |
initial r_setup = INITIAL_SETUP; |
initial r_setup = INITIAL_SETUP[29:0]; |
always @(posedge i_clk) |
if (state >= `RXU_RESET_IDLE) |
r_setup <= i_setup; |
r_setup <= i_setup[29:0]; |
|
|
// Our monster state machine. YIKES! |
/txuart.v
21,9 → 21,16
// Now for the setup register. The register is 32 bits, so that this |
// UART may be set up over a 32-bit bus. |
// |
// i_setup[30] Set this to zero to use hardware flow control, and to |
// one to ignore hardware flow control. Only works if the hardware |
// flow control has been properly wired. |
// |
// If you don't want hardware flow control, fix the i_rts bit to |
// 1'b1, and let the synthesys tools optimize out the logic. |
// |
// i_setup[29:28] Indicates the number of data bits per word. This will |
// either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10 |
// for a six bit word, or 2'b11 for a five bit word. |
// either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10 |
// for a six bit word, or 2'b11 for a five bit word. |
// |
// i_setup[27] Indicates whether or not to use one or two stop bits. |
// Set this to one to expect two stop bits, zero for one. |
62,7 → 69,7
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// Copyright (C) 2015-2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
75,7 → 82,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
104,29 → 111,39
`define TXU_IDLE 4'hf |
// |
// |
module txuart(i_clk, i_reset, i_setup, i_break, i_wr, i_data,o_uart_tx, o_busy); |
parameter INITIAL_SETUP = 30'd868; |
module txuart(i_clk, i_reset, i_setup, i_break, i_wr, i_data, |
i_rts, o_uart_tx, o_busy); |
parameter [30:0] INITIAL_SETUP = 31'd868; |
input i_clk, i_reset; |
input [29:0] i_setup; |
input [30:0] i_setup; |
input i_break; |
input i_wr; |
input [7:0] i_data; |
// Hardware flow control Ready-To-Send bit. Set this to one to use |
// the core without flow control. (A more appropriate name would be |
// the Ready-To-Receive bit ...) |
input i_rts; |
// And the UART input line itself |
output reg o_uart_tx; |
// A line to tell others when we are ready to accept data. If |
// (i_wr)&&(!o_busy) is ever true, then the core has accepted a byte |
// for transmission. |
output wire o_busy; |
|
wire [27:0] clocks_per_baud, break_condition; |
wire [1:0] data_bits; |
wire use_parity, parity_even, dblstop, fixd_parity, |
fixdp_value; |
reg [29:0] r_setup; |
fixdp_value, hw_flow_control; |
reg [30:0] r_setup; |
assign clocks_per_baud = { 4'h0, r_setup[23:0] }; |
assign break_condition = { r_setup[23:0], 4'h0 }; |
assign data_bits = r_setup[29:28]; |
assign dblstop = r_setup[27]; |
assign use_parity = r_setup[26]; |
assign fixd_parity = r_setup[25]; |
assign parity_even = r_setup[24]; |
assign fixdp_value = r_setup[24]; |
assign hw_flow_control = !r_setup[30]; |
assign data_bits = r_setup[29:28]; |
assign dblstop = r_setup[27]; |
assign use_parity = r_setup[26]; |
assign fixd_parity = r_setup[25]; |
assign parity_even = r_setup[24]; |
assign fixdp_value = r_setup[24]; |
|
reg [27:0] baud_counter; |
reg [3:0] state; |
133,6 → 150,29
reg [7:0] lcl_data; |
reg calc_parity, r_busy, zero_baud_counter; |
|
|
// First step ... handle any hardware flow control, if so enabled. |
// |
// Clock in the flow control data, two clocks to avoid metastability |
// Default to using hardware flow control (uart_setup[30]==0 to use it). |
// Set this high order bit off if you do not wish to use it. |
reg q_rts, qq_rts, ck_rts; |
// While we might wish to give initial values to q_rts and ck_rts, |
// 1) it's not required since the transmitter starts in a long wait |
// state, and 2) doing so will prevent the synthesizer from optimizing |
// this pin in the case it is hard set to 1'b1 external to this |
// peripheral. |
// |
// initial q_rts = 1'b0; |
// initial qq_rts = 1'b0; |
// initial ck_rts = 1'b0; |
always @(posedge i_clk) |
q_rts <= i_rts; |
always @(posedge i_clk) |
qq_rts <= q_rts; |
always @(posedge i_clk) |
ck_rts <= (qq_rts)&&(hw_flow_control); |
|
initial o_uart_tx = 1'b1; |
initial r_busy = 1'b1; |
initial state = `TXU_IDLE; |
168,7 → 208,7
2'b11: state <= `TXU_BIT_THREE; |
endcase |
end else begin // Stay in idle |
r_busy <= 0; |
r_busy <= !ck_rts; |
end |
end else begin |
// One clock tick in each of these states ... |
215,7 → 255,7
// broken out up top, and indicate what 1) our baud rate is, 2) our |
// number of stop bits, 3) what type of parity we are using, and 4) |
// the size of our data word. |
initial r_setup = INITIAL_SETUP; |
initial r_setup = INITIAL_SETUP[30:0]; |
always @(posedge i_clk) |
if (state == `TXU_IDLE) |
r_setup <= i_setup; |
/ufifo.v
11,7 → 11,7
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// Copyright (C) 2015-2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
24,7 → 24,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
35,16 → 35,16
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
module ufifo(i_clk, i_rst, i_wr, i_data, i_rd, o_data, |
o_empty_n, o_half_full, o_status, o_err); |
parameter BW=8, LGFLEN=4; |
module ufifo(i_clk, i_rst, i_wr, i_data, o_empty_n, i_rd, o_data, o_status, o_err); |
parameter BW=8; // Byte/data width |
parameter [3:0] LGFLEN=4; |
parameter [0:0] RXFIFO=0; |
input i_clk, i_rst; |
input i_wr; |
input [(BW-1):0] i_data; |
output wire o_empty_n; // True if something is in FIFO |
input i_rd; |
output wire [(BW-1):0] o_data; |
output reg o_empty_n; |
output wire o_half_full; |
output wire [15:0] o_status; |
output wire o_err; |
|
103,7 → 103,7
// 5 1 2 fifo[2] |
// 6 0 3 fifo[3] |
// 7 0 3 fifo[3] |
reg will_underflow, r_unfl; |
reg will_underflow; |
initial will_underflow = 1'b1; |
always @(posedge i_clk) |
if (i_rst) |
115,7 → 115,13
else |
will_underflow <= (r_last == r_first); |
|
initial r_unfl = 1'b0; |
// |
// Don't report FIFO underflow errors. These'll be caught elsewhere |
// in the system, and the logic below makes it hard to reset them. |
// We'll still report FIFO overflow, however. |
// |
// reg r_unfl; |
// initial r_unfl = 1'b0; |
initial r_last = 0; |
always @(posedge i_clk) |
if (i_rst) |
122,7 → 128,7
begin |
r_last <= 0; |
r_next <= { {(LGFLEN-1){1'b0}}, 1'b1 }; |
r_unfl <= 1'b0; |
// r_unfl <= 1'b0; |
end else if (i_rd) |
begin |
if ((i_wr)||(!will_underflow)) // (r_first != r_last) |
133,8 → 139,8
// Need to be prepared for a possible two |
// reads in quick succession |
// o_data <= fifo[r_last+1]; |
end else |
r_unfl <= 1'b1; |
end |
// else r_unfl <= 1'b1; |
end |
|
reg [7:0] fifo_here, fifo_next, r_data; |
161,32 → 167,89
// wire [(LGFLEN-1):0] current_fill; |
// assign current_fill = (r_first-r_last); |
|
reg r_empty_n; |
initial r_empty_n = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
o_empty_n <= 1'b0; |
r_empty_n <= 1'b0; |
else case({i_wr, i_rd}) |
2'b00: o_empty_n <= (r_first != r_last); |
2'b11: o_empty_n <= (r_first != r_last); |
2'b10: o_empty_n <= 1'b1; |
2'b01: o_empty_n <= (r_first != w_last_plus_one); |
2'b00: r_empty_n <= (r_first != r_last); |
2'b11: r_empty_n <= (r_first != r_last); |
2'b10: r_empty_n <= 1'b1; |
2'b01: r_empty_n <= (r_first != w_last_plus_one); |
endcase |
|
wire w_full_n; |
assign w_full_n = will_overflow; |
|
// |
// If this is a receive FIFO, the FIFO count that matters is the number |
// of values yet to be read. If instead this is a transmit FIFO, then |
// the FIFO count that matters is the number of empty positions that |
// can still be filled before the FIFO is full. |
// |
// Adjust for these differences here. |
reg [(LGFLEN-1):0] r_fill; |
always @(posedge i_clk) |
if (i_rst) |
r_fill <= 0; |
else if ((i_rd)&&(!i_wr)) |
r_fill <= r_first - r_next; |
else if ((!i_rd)&&(i_wr)) |
r_fill <= r_first - r_last + 1'b1; |
else |
r_fill <= r_first - r_last; |
assign o_half_full = r_fill[(LGFLEN-1)]; |
generate if (RXFIFO!=0) begin |
// Calculate the number of elements in our FIFO |
// |
// Although used for receive, this is actually the more generic |
// answer--should you wish to use the FIFO in another context. |
always @(posedge i_clk) |
if (i_rst) |
r_fill <= 0; |
else case({i_wr, i_rd}) |
2'b01: r_fill <= r_first - r_next; |
2'b10: r_fill <= r_first - r_last + 1'b1; |
default: r_fill <= r_first - r_last; |
endcase |
end else begin |
// Calculate the number of elements that are empty and can be |
// filled within our FIFO |
always @(posedge i_clk) |
if (i_rst) |
r_fill <= { (LGFLEN){1'b1} }; |
else case({i_wr, i_rd}) |
2'b01: r_fill <= r_last - r_first; |
2'b10: r_fill <= r_last - w_first_plus_two; |
default: r_fill <= r_last - w_first_plus_one; |
endcase |
end endgenerate |
|
assign o_err = (r_ovfl) || (r_unfl); |
// We don't report underflow errors. These |
assign o_err = (r_ovfl); // || (r_unfl); |
|
wire [3:0] lglen; |
assign lglen = LGFLEN; |
assign o_status = { lglen, {(16-2-4-LGFLEN){1'b0}}, r_fill, o_half_full, o_empty_n }; |
|
wire [9:0] w_fill; |
assign w_fill[(LGFLEN-1):0] = r_fill; |
generate if (LGFLEN != 10) |
assign w_fill[9:(LGFLEN-1)] = 0; |
endgenerate |
|
wire w_half_full; |
assign w_half_full = r_fill[(LGFLEN-1)]; |
|
assign o_status = { |
// Our status includes a 4'bit nibble telling anyone reading |
// this the size of our FIFO. The size is then given by |
// 2^(this value). Hence a 4'h4 in this position means that the |
// FIFO has 2^4 or 16 values within it. |
lglen, |
// The FIFO fill--for a receive FIFO the number of elements |
// left to be read, and for a transmit FIFO the number of |
// empty elements within the FIFO that can yet be filled. |
w_fill, |
// A '1' here means a half FIFO length can be read (receive |
// FIFO) or written to (not a receive FIFO). |
// receive FIFO), or be written to (if it isn't). |
(RXFIFO!=0)?w_half_full:w_half_full, |
// A '1' here means the FIFO can be read from (if it is a |
// receive FIFO), or be written to (if it isn't). |
(RXFIFO!=0)?r_empty_n:w_full_n |
}; |
|
assign o_empty_n = r_empty_n; |
|
endmodule |
/wbuart-insert.v
50,12 → 50,12
// it to CLKRATE / BAUDRATE, to give me 8N1 performance. 4MB is useful |
// to me, so 100MHz / 4M = 25 could be the setup. You can also use |
// 200MHz / 4MB = 50 ... it all depends upon your clock. |
`define UART_SETUP 30'd25 |
reg [29:0] uart_setup; |
`define UART_SETUP 31'd25 |
reg [30:0] uart_setup; |
initial uart_setup = `UART_SETUP; |
always @(posedge i_clk) |
if ((i_wb_stb)&&(i_wb_addr == `UART_SETUP_ADDR)) |
uart_setup[29:0] <= i_wb_data[29:0]; |
uart_setup[30:0] <= i_wb_data[30:0]; |
|
// |
// First the UART receiver |
83,7 → 83,7
r_rx_data[ 9] <= (rx_perr) && (!i_wb_data[ 9]); |
end |
always @(posedge i_clk) |
if(((i_wb_stb)&&(~i_wb_we)&&(i_wb_addr == `UART_RX_ADDR)) |
if(((i_wb_stb)&&(!i_wb_we)&&(i_wb_addr == `UART_RX_ADDR)) |
||(rx_stb)) |
r_rx_data[8] <= !rx_stb; |
assign o_cts = !r_rx_data[8]; |
90,9 → 90,19
assign rx_data = { 20'h00, r_rx_data }; |
assign rx_int = !r_rx_data[8]; |
|
// Transmit hardware flow control, the rts line |
wire rts; |
// Set this rts value to one if you aren't ever going to use H/W flow |
// control, otherwise set it to the value coming in from the external |
// i_rts pin. |
assign rts = i_rts; |
|
// |
// Then the UART transmitter |
// |
// |
// |
// Now onto the transmitter itself |
wire tx_busy; |
reg [7:0] r_tx_data; |
reg r_tx_stb, r_tx_break; |
99,19 → 109,19
wire [31:0] tx_data; |
txuart #(UART_SETUP) tx(i_clk, 1'b0, uart_setup, |
r_tx_break, r_tx_stb, r_tx_data, |
o_tx, tx_busy); |
rts, o_tx, tx_busy); |
always @(posedge i_clk) |
if ((i_wb_stb)&&(i_wb_addr == 5'h0f)) |
begin |
r_tx_stb <= (!r_tx_break)&&(!i_wb_data[8]); |
r_tx_stb <= (!r_tx_break)&&(!i_wb_data[8]); |
r_tx_data <= i_wb_data[7:0]; |
r_tx_break<= i_wb_data[9]; |
end else if (~tx_busy) |
end else if (!tx_busy) |
begin |
r_tx_stb <= 1'b0; |
r_tx_data <= 8'h0; |
end |
assign tx_data = { 20'h00, |
assign tx_data = { 16'h00, rts, 3'h0, |
ck_uart, o_tx, r_tx_break, tx_busy, |
r_tx_data }; |
assign tx_int = ~tx_busy; |
118,7 → 128,7
|
always @(posedge i_clk) |
case(i_wb_addr) |
`UART_SETUP_ADDR: o_wb_data <= { 2'b00, uart_setup }; |
`UART_SETUP_ADDR: o_wb_data <= { 1'b0, uart_setup }; |
`UART_RX_ADDR : o_wb_data <= rx_data; |
`UART_TX_ADDR : o_wb_data <= tx_data; |
// |
/wbuart.v
27,7 → 27,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
45,15 → 45,21
module wbuart(i_clk, i_rst, |
// |
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, |
o_wb_stall, o_wb_ack, o_wb_data, |
o_wb_ack, o_wb_stall, o_wb_data, |
// |
i_uart_rx, o_uart_tx, |
i_uart_rx, o_uart_tx, i_rts, o_cts, |
// i_uart_rts, o_uart_cts, i_uart_dtr, o_uart_dts |
// |
o_uart_rx_int, o_uart_tx_int, |
o_uart_rxfifo_int, o_uart_txfifo_int); |
parameter INITIAL_SETUP = 30'd25, // 4MB 8N1, when using 100MHz clock |
LGFLEN = 4; |
parameter [30:0] INITIAL_SETUP = 31'd25; // 4MB 8N1, when using 100MHz clock |
parameter [3:0] LGFLEN = 4; |
parameter [0:0] HARDWARE_FLOW_CONTROL_PRESENT = 1'b1; |
// Perform a simple/quick bounds check on the log FIFO length, to make |
// sure its within the bounds we can support with our current |
// interface. |
localparam [3:0] LCLLGFLEN = (LGFLEN > 4'ha)? 4'ha |
: ((LGFLEN < 4'h2) ? 4'h2 : LGFLEN); |
// |
input i_clk, i_rst; |
// Wishbone inputs |
60,12 → 66,24
input i_wb_cyc, i_wb_stb, i_wb_we; |
input [1:0] i_wb_addr; |
input [31:0] i_wb_data; |
output reg o_wb_ack; |
output wire o_wb_stall; |
output reg o_wb_ack; |
output reg [31:0] o_wb_data; |
// |
input i_uart_rx; |
output wire o_uart_tx; |
// RTS is used for hardware flow control. According to Wikipedia, it |
// should probably be renamed RTR for "ready to receive". It tell us |
// whether or not the receiving hardware is ready to accept another |
// byte. If low, the transmitter will pause. |
// |
// If you don't wish to use hardware flow control, just set i_rts to |
// 1'b1 and let the optimizer simply remove this logic. |
input i_rts; |
// CTS is the "Clear-to-send" signal. We set it anytime our FIFO |
// isn't full. Feel free to ignore this output if you do not wish to |
// use flow control. |
output reg o_cts; |
output wire o_uart_rx_int, o_uart_tx_int, |
o_uart_rxfifo_int, o_uart_txfifo_int; |
|
75,7 → 93,7
// The UART setup parameters: bits per byte, stop bits, parity, and |
// baud rate are all captured within this uart_setup register. |
// |
reg [29:0] uart_setup; |
reg [30:0] uart_setup; |
initial uart_setup = INITIAL_SETUP; |
always @(posedge i_clk) |
// Under wishbone rules, a write takes place any time i_wb_stb |
82,11 → 100,18
// is high. If that's the case, and if the write was to the |
// setup address, then set us up for the new parameters. |
if ((i_wb_stb)&&(i_wb_addr == `UART_SETUP)&&(i_wb_we)) |
uart_setup[29:0] <= i_wb_data[29:0]; |
uart_setup <= { |
(i_wb_data[30]) |
||(!HARDWARE_FLOW_CONTROL_PRESENT), |
i_wb_data[29:0] }; |
|
///////////////////////////////////////// |
// |
// First the UART receiver |
// |
// First, the UART receiver |
// |
// |
///////////////////////////////////////// |
|
// First the wires/registers this receiver depends upon |
wire rx_stb, rx_break, rx_perr, rx_ferr, ck_uart; |
126,18 → 151,32
// four status-type values: 1) is it non-empty, 2) is the FIFO over half |
// full, 3) a 16-bit status register, containing info regarding how full |
// the FIFO truly is, and 4) an error indicator. |
ufifo #(.LGFLEN(LGFLEN)) |
ufifo #(.LGFLEN(LCLLGFLEN), .RXFIFO(1)) |
rxfifo(i_clk, (i_rst)||(rx_break)||(rx_uart_reset), |
rx_stb, rx_uart_data, |
rx_empty_n, |
rxf_wb_read, rxf_wb_data, |
(rx_empty_n), (o_uart_rxfifo_int), |
rxf_status, rx_fifo_err); |
assign o_uart_rxfifo_int = rxf_status[1]; |
|
// We produce four interrupts. One of the receive interrupts indicates |
// whether or not the receive FIFO is non-empty. This should wake up |
// the CPU. |
assign o_uart_rx_int = !rx_empty_n; |
assign o_uart_rx_int = rxf_status[0]; |
|
// The clear to send line, which may be ignored, but which we set here |
// to be true any time the FIFO has fewer than N-2 items in it. |
// Why N-1? Because at N-1 we are totally full, but already so full |
// that if the transmit end starts sending we won't have a location to |
// receive it. (Transmit might've started on the next character by the |
// time we set this--need to set it to one character before necessary |
// thus.) |
wire [(LCLLGFLEN-1):0] check_cutoff; |
assign check_cutoff = -3; |
always @(posedge i_clk) |
o_cts = (!HARDWARE_FLOW_CONTROL_PRESENT) |
||(rxf_status[(LCLLGFLEN+1):2] > check_cutoff); |
|
// If the bus requests that we read from the receive FIFO, we need to |
// tell this to the receive FIFO. Note that because we are using a |
// clock here, the output from the receive FIFO will necessarily be |
204,10 → 243,14
rx_break, rx_ferr, r_rx_perr, !rx_empty_n, |
rxf_wb_data}; |
|
///////////////////////////////////////// |
// |
// |
// Then the UART transmitter |
// |
wire tx_empty_n, txf_half_full, txf_err; |
// |
///////////////////////////////////////// |
wire tx_empty_n, txf_err; |
wire [7:0] tx_data; |
wire [15:0] txf_status; |
reg r_tx_break, txf_wb_write, tx_uart_reset; |
238,18 → 281,20
// break. We read from the FIFO any time the UART transmitter is idle. |
// and ... we just set the values (above) for controlling writing into |
// this. |
ufifo #(.LGFLEN(LGFLEN)) |
ufifo #(.LGFLEN(LGFLEN), .RXFIFO(0)) |
txfifo(i_clk, (r_tx_break)||(tx_uart_reset), |
txf_wb_write, txf_wb_data, |
(~tx_busy)&&(tx_empty_n), tx_data, |
tx_empty_n, txf_half_full, txf_status, txf_err); |
tx_empty_n, |
(!tx_busy)&&(tx_empty_n), tx_data, |
txf_status, txf_err); |
// Let's create two transmit based interrupts from the FIFO for the CPU. |
// The first will be true any time the FIFO is empty. |
assign o_uart_tx_int = !tx_empty_n; |
// The first will be true any time the FIFO has at least one open |
// position within it. |
assign o_uart_tx_int = txf_status[0]; |
// The second will be true any time the FIFO is less than half |
// full, allowing us a change to always keep it (near) fully |
// charged. |
assign o_uart_txfifo_int = !txf_half_full; |
assign o_uart_txfifo_int = txf_status[1]; |
|
// Break logic |
// |
281,6 → 326,8
else |
tx_uart_reset <= 1'b0; |
|
wire rts; |
assign rts = (!HARDWARE_FLOW_CONTROL_PRESENT)||(i_rts); |
// Finally, the UART transmitter module itself. Note that we haven't |
// connected the reset wire. Transmitting is as simple as setting |
// the stb value (here set to tx_empty_n) and the data. When these |
292,7 → 339,7
// starting to transmit a new byte.) |
txuart #(INITIAL_SETUP) tx(i_clk, 1'b0, uart_setup, |
r_tx_break, (tx_empty_n), tx_data, |
o_uart_tx, tx_busy); |
i_rts, o_uart_tx, tx_busy); |
|
// Now that we are done with the chain, pick some wires for the user |
// to read on any read of the transmit port. |
302,15 → 349,15
// the receive FIFO, here only writing to the transmit port advances the |
// transmit FIFO--hence the read values are free for ... whatever.) |
// We choose here to provide information about the transmit FIFO |
// (txf_err, txf_half_full, tx_empty_n), information about the current |
// (txf_err, txf_half_full, txf_full_n), information about the current |
// voltage on the line (o_uart_tx)--and even the voltage on the receive |
// line (ck_uart), as well as our current setting of the break and |
// whether or not we are actively transmitting. |
wire [31:0] wb_tx_data; |
assign wb_tx_data = { 16'h00, |
1'h0, txf_half_full, tx_empty_n, txf_err, |
ck_uart, o_uart_tx, r_tx_break, tx_busy, |
txf_wb_data}; |
i_rts, txf_status[1:0], txf_err, |
ck_uart, o_uart_tx, r_tx_break, (tx_busy|txf_status[0]), |
(tx_busy|txf_status[0])?txf_wb_data:8'b00}; |
|
// Each of the FIFO's returns a 16 bit status value. This value tells |
// us both how big the FIFO is, as well as how much of the FIFO is in |
339,7 → 386,7
// interconnect, etc. For this reason, we can just simplify our logic. |
always @(posedge i_clk) |
casez(r_wb_addr) |
`UART_SETUP: o_wb_data <= { 2'b00, uart_setup }; |
`UART_SETUP: o_wb_data <= { 1'b0, uart_setup }; |
`UART_FIFO: o_wb_data <= wb_fifo_data; |
`UART_RXREG: o_wb_data <= wb_rx_data; |
`UART_TXREG: o_wb_data <= wb_tx_data; |