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 14 to Rev 15
- ↔ Reverse comparison
Rev 14 → Rev 15
/Makefile
49,15 → 49,25
test: $(VDIRFB)/Vtxuart__ALL.a |
test: $(VDIRFB)/Vrxuart__ALL.a |
test: $(VDIRFB)/Vwbuart__ALL.a |
test: $(VDIRFB)/Vtxuartlite__ALL.a |
test: $(VDIRFB)/Vrxuartlite__ALL.a |
|
$(VDIRFB)/Vrxuart__ALL.a: $(VDIRFB)/Vrxuart.h $(VDIRFB)/Vrxuart.cpp |
$(VDIRFB)/Vrxuart__ALL.a: $(VDIRFB)/Vrxuart.mk |
$(VDIRFB)/Vrxuart.h $(VDIRFB)/Vrxuart.cpp $(VDIRFB)/Vrxuart.mk: rxuart.v |
|
$(VDIRFB)/Vrxuartlite__ALL.a: $(VDIRFB)/Vrxuartlite.h $(VDIRFB)/Vrxuartlite.cpp |
$(VDIRFB)/Vrxuartlite__ALL.a: $(VDIRFB)/Vrxuartlite.mk |
$(VDIRFB)/Vrxuartlite.h $(VDIRFB)/Vrxuartlite.cpp $(VDIRFB)/Vrxuartlite.mk: rxuartlite.v |
|
$(VDIRFB)/Vtxuart__ALL.a: $(VDIRFB)/Vtxuart.h $(VDIRFB)/Vtxuart.cpp |
$(VDIRFB)/Vtxuart__ALL.a: $(VDIRFB)/Vtxuart.mk |
$(VDIRFB)/Vtxuart.h $(VDIRFB)/Vtxuart.cpp $(VDIRFB)/Vtxuart.mk: txuart.v |
|
$(VDIRFB)/Vtxuartlite__ALL.a: $(VDIRFB)/Vtxuartlite.h $(VDIRFB)/Vtxuartlite.cpp |
$(VDIRFB)/Vtxuartlite__ALL.a: $(VDIRFB)/Vtxuartlite.mk |
$(VDIRFB)/Vtxuartlite.h $(VDIRFB)/Vtxuartlite.cpp $(VDIRFB)/Vtxuartlite.mk: txuartlite.v |
|
$(VDIRFB)/Vwbuart__ALL.a: $(VDIRFB)/Vwbuart.h $(VDIRFB)/Vwbuart.cpp |
$(VDIRFB)/Vwbuart__ALL.a: $(VDIRFB)/Vwbuart.mk |
$(VDIRFB)/Vwbuart.h $(VDIRFB)/Vwbuart.cpp $(VDIRFB)/Vwbuart.mk: wbuart.v ufifo.v txuart.v rxuart.v |
/rxuartlite.v
0,0 → 1,197
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: rxuartlite.v |
// |
// Project: wbuart32, a full featured UART with simulator |
// |
// Purpose: Receive and decode inputs from a single UART line. |
// |
// |
// To interface with this module, connect it to your system clock, |
// and a UART input. Set the parameter to the number of clocks per |
// baud. When data becomes available, the o_wr line will be asserted |
// for one clock cycle. |
// |
// This interface only handles 8N1 serial port communications. It does |
// not handle the break, parity, or frame error conditions. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// 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 |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// 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 |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
`define RXU_BIT_ZERO 4'h0 |
`define RXU_BIT_ONE 4'h1 |
`define RXU_BIT_TWO 4'h2 |
`define RXU_BIT_THREE 4'h3 |
`define RXU_BIT_FOUR 4'h4 |
`define RXU_BIT_FIVE 4'h5 |
`define RXU_BIT_SIX 4'h6 |
`define RXU_BIT_SEVEN 4'h7 |
// `define RXU_PARITY 4'h8 // Unused in RXUARTLITE |
`define RXU_STOP 4'h8 |
// `define RXU_SECOND_STOP 4'ha // Unused in RXUARTLITE |
// Unused 4'hb |
// Unused 4'hc |
// `define RXU_BREAK 4'hd // Unused in RXUARTLITE |
// `define RXU_RESET_IDLE 4'he // Unused in RXUARTLITE |
`define RXU_IDLE 4'hf |
|
module rxuartlite(i_clk, i_uart_rx, o_wr, o_data); |
parameter [23:0] CLOCKS_PER_BAUD = 24'd868; |
input i_clk; |
input i_uart_rx; |
output reg o_wr; |
output reg [7:0] o_data; |
|
|
wire [23:0] clocks_per_baud, half_baud; |
reg [3:0] state; |
|
assign half_baud = { 1'b0, CLOCKS_PER_BAUD[23:1] } - 24'h1; |
reg [23:0] baud_counter; |
reg zero_baud_counter; |
|
|
// Since this is an asynchronous receiver, we need to register our |
// input a couple of clocks over to avoid any problems with |
// metastability. We do that here, and then ignore all but the |
// ck_uart wire. |
reg q_uart, qq_uart, ck_uart; |
initial q_uart = 1'b0; |
initial qq_uart = 1'b0; |
initial ck_uart = 1'b0; |
always @(posedge i_clk) |
begin |
q_uart <= i_uart_rx; |
qq_uart <= q_uart; |
ck_uart <= qq_uart; |
end |
|
// Keep track of the number of clocks since the last change. |
// |
// This is used to determine if we are in either a break or an idle |
// condition, as discussed further below. |
reg [23:0] chg_counter; |
initial chg_counter = 24'h00; |
always @(posedge i_clk) |
if (qq_uart != ck_uart) |
chg_counter <= 24'h00; |
else |
chg_counter <= chg_counter + 1; |
|
// Are we in the middle of a baud iterval? Specifically, are we |
// in the middle of a start bit? Set this to high if so. We'll use |
// this within our state machine to transition out of the IDLE |
// state. |
reg half_baud_time; |
initial half_baud_time = 0; |
always @(posedge i_clk) |
half_baud_time <= (~ck_uart)&&(chg_counter >= half_baud); |
|
|
initial state = `RXU_IDLE; |
always @(posedge i_clk) |
begin |
if (state == `RXU_IDLE) |
begin // Idle state, independent of baud counter |
// By default, just stay in the IDLE state |
state <= `RXU_IDLE; |
if ((~ck_uart)&&(half_baud_time)) |
// UNLESS: We are in the center of a valid |
// start bit |
state <= `RXU_BIT_ZERO; |
end else if (zero_baud_counter) |
begin |
if (state < `RXU_STOP) |
// Data arrives least significant bit first. |
// By the time this is clocked in, it's what |
// you'll have. |
state <= state + 1; |
else // Wait for the next character |
state <= `RXU_IDLE; |
end |
end |
|
// Data bit capture logic. |
// |
// This is drastically simplified from the state machine above, based |
// upon: 1) it doesn't matter what it is until the end of a captured |
// byte, and 2) the data register will flush itself of any invalid |
// data in all other cases. Hence, let's keep it real simple. |
reg [7:0] data_reg; |
always @(posedge i_clk) |
if (zero_baud_counter) |
data_reg <= { ck_uart, data_reg[7:1] }; |
|
// Our data bit logic doesn't need nearly the complexity of all that |
// work above. Indeed, we only need to know if we are at the end of |
// a stop bit, in which case we copy the data_reg into our output |
// data register, o_data, and tell others (for one clock) that data is |
// available. |
// |
initial o_data = 8'h00; |
reg pre_wr; |
initial pre_wr = 1'b0; |
always @(posedge i_clk) |
if ((zero_baud_counter)&&(state == `RXU_STOP)) |
begin |
o_wr <= 1'b1; |
o_data <= data_reg; |
end else |
o_wr <= 1'b0; |
|
// The baud counter |
// |
// This is used as a "clock divider" if you will, but the clock needs |
// to be reset before any byte can be decoded. In all other respects, |
// we set ourselves up for clocks_per_baud counts between baud |
// intervals. |
always @(posedge i_clk) |
if ((zero_baud_counter)|||(state == `RXU_IDLE)) |
baud_counter <= CLOCKS_PER_BAUD-1'b1; |
else |
baud_counter <= baud_counter-1'b1; |
|
// zero_baud_counter |
// |
// Rather than testing whether or not (baud_counter == 0) within our |
// (already too complicated) state transition tables, we use |
// zero_baud_counter to pre-charge that test on the clock |
// before--cleaning up some otherwise difficult timing dependencies. |
initial zero_baud_counter = 1'b0; |
always @(posedge i_clk) |
if (state == `RXU_IDLE) |
zero_baud_counter <= 1'b0; |
else |
zero_baud_counter <= (baud_counter == 24'h01); |
|
|
endmodule |
|
|
/txuart.v
112,7 → 112,7
// |
// |
module txuart(i_clk, i_reset, i_setup, i_break, i_wr, i_data, |
i_rts, o_uart_tx, o_busy); |
i_cts_n, o_uart_tx, o_busy); |
parameter [30:0] INITIAL_SETUP = 31'd868; |
input i_clk, i_reset; |
input [30:0] i_setup; |
122,7 → 122,7
// 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; |
input i_cts_n; |
// And the UART input line itself |
output reg o_uart_tx; |
// A line to tell others when we are ready to accept data. If |
156,22 → 156,22
// 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, |
reg q_cts_n, qq_cts_n, ck_cts; |
// While we might wish to give initial values to q_rts and ck_cts, |
// 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; |
// initial q_cts_n = 1'b1; |
// initial qq_cts_n = 1'b1; |
// initial ck_cts = 1'b0; |
always @(posedge i_clk) |
q_rts <= i_rts; |
q_cts_n <= i_cts_n; |
always @(posedge i_clk) |
qq_rts <= q_rts; |
qq_cts_n <= q_cts_n; |
always @(posedge i_clk) |
ck_rts <= (qq_rts)||(!hw_flow_control); |
ck_cts <= (!qq_cts_n)||(!hw_flow_control); |
|
initial o_uart_tx = 1'b1; |
initial r_busy = 1'b1; |
208,7 → 208,7
2'b11: state <= `TXU_BIT_THREE; |
endcase |
end else begin // Stay in idle |
r_busy <= !ck_rts; |
r_busy <= !ck_cts; |
end |
end else begin |
// One clock tick in each of these states ... |
/txuartlite.v
0,0 → 1,206
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: txuartlite.v |
// |
// Project: wbuart32, a full featured UART with simulator |
// |
// Purpose: Transmit outputs over a single UART line. This particular UART |
// implementation has been extremely simplified: it does not handle |
// generating break conditions, nor does it handle anything other than the |
// 8N1 (8 data bits, no parity, 1 stop bit) UART sub-protocol. |
// |
// To interface with this module, connect it to your system clock, and |
// pass it the byte of data you wish to transmit. Strobe the i_wr line |
// high for one cycle, and your data will be off. Wait until the 'o_busy' |
// line is low before strobing the i_wr line again--this implementation |
// has NO BUFFER, so strobing i_wr while the core is busy will just |
// get ignored. The output will be placed on the o_txuart output line. |
// |
// (I often set both data and strobe on the same clock, and then just leave |
// them set until the busy line is low. Then I move on to the next piece |
// of data.) |
// |
// Creator: Dan Gisselquist, Ph.D. |
// 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 |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// 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 |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
`define TXU_BIT_ZERO 4'h0 |
`define TXU_BIT_ONE 4'h1 |
`define TXU_BIT_TWO 4'h2 |
`define TXU_BIT_THREE 4'h3 |
`define TXU_BIT_FOUR 4'h4 |
`define TXU_BIT_FIVE 4'h5 |
`define TXU_BIT_SIX 4'h6 |
`define TXU_BIT_SEVEN 4'h7 |
`define TXU_STOP 4'h8 |
`define TXU_IDLE 4'hf |
// |
// |
module txuartlite(i_clk, i_wr, i_data, o_uart_tx, o_busy); |
parameter [23:0] CLOCKS_PER_BAUD = 24'd868; |
input i_clk; |
input i_wr; |
input [7:0] i_data; |
// 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; |
|
reg [23:0] baud_counter; |
reg [3:0] state; |
reg [7:0] lcl_data; |
reg r_busy, zero_baud_counter; |
|
initial r_busy = 1'b1; |
initial state = `TXU_IDLE; |
initial lcl_data= 8'h0; |
always @(posedge i_clk) |
begin |
if (!zero_baud_counter) |
// r_busy needs to be set coming into here |
r_busy <= 1'b1; |
else if (state == `TXU_IDLE) // STATE_IDLE |
begin |
r_busy <= 1'b0; |
if ((i_wr)&&(!r_busy)) |
begin // Immediately start us off with a start bit |
r_busy <= 1'b1; |
state <= `TXU_BIT_ZERO; |
end |
end else begin |
// One clock tick in each of these states ... |
r_busy <= 1'b1; |
if (state <=`TXU_STOP) // start bit, 8-d bits, stop-b |
state <= state + 1; |
else |
state <= `TXU_IDLE; |
end |
end |
|
// o_busy |
// |
// This is a wire, designed to be true is we are ever busy above. |
// originally, this was going to be true if we were ever not in the |
// idle state. The logic has since become more complex, hence we have |
// a register dedicated to this and just copy out that registers value. |
assign o_busy = (r_busy); |
|
|
// lcl_data |
// |
// This is our working copy of the i_data register which we use |
// when transmitting. It is only of interest during transmit, and is |
// allowed to be whatever at any other time. Hence, if r_busy isn't |
// true, we can always set it. On the one clock where r_busy isn't |
// true and i_wr is, we set it and r_busy is true thereafter. |
// Then, on any zero_baud_counter (i.e. change between baud intervals) |
// we simple logically shift the register right to grab the next bit. |
initial lcl_data = 8'hff; |
always @(posedge i_clk) |
if ((i_wr)&&(!r_busy)) |
lcl_data <= i_data; |
else if (zero_baud_counter) |
lcl_data <= { 1'b1, lcl_data[7:1] }; |
|
// o_uart_tx |
// |
// This is the final result/output desired of this core. It's all |
// centered about o_uart_tx. This is what finally needs to follow |
// the UART protocol. |
// |
initial o_uart_tx = 1'b1; |
always @(posedge i_clk) |
if ((i_wr)&&(!r_busy)) |
o_uart_tx <= 1'b0; // Set the start bit on writes |
else if (zero_baud_counter) // Set the data bit. |
o_uart_tx <= lcl_data[0]; |
|
|
// All of the above logic is driven by the baud counter. Bits must last |
// CLOCKS_PER_BAUD in length, and this baud counter is what we use to |
// make certain of that. |
// |
// The basic logic is this: at the beginning of a bit interval, start |
// the baud counter and set it to count CLOCKS_PER_BAUD. When it gets |
// to zero, restart it. |
// |
// However, comparing a 28'bit number to zero can be rather complex-- |
// especially if we wish to do anything else on that same clock. For |
// that reason, we create "zero_baud_counter". zero_baud_counter is |
// nothing more than a flag that is true anytime baud_counter is zero. |
// It's true when the logic (above) needs to step to the next bit. |
// Simple enough? |
// |
// I wish we could stop there, but there are some other (ugly) |
// conditions to deal with that offer exceptions to this basic logic. |
// |
// 1. When the user has commanded a BREAK across the line, we need to |
// wait several baud intervals following the break before we start |
// transmitting, to give any receiver a chance to recognize that we are |
// out of the break condition, and to know that the next bit will be |
// a stop bit. |
// |
// 2. A reset is similar to a break condition--on both we wait several |
// baud intervals before allowing a start bit. |
// |
// 3. In the idle state, we stop our counter--so that upon a request |
// to transmit when idle we can start transmitting immediately, rather |
// than waiting for the end of the next (fictitious and arbitrary) baud |
// interval. |
// |
// When (i_wr)&&(!r_busy)&&(state == `TXU_IDLE) then we're not only in |
// the idle state, but we also just accepted a command to start writing |
// the next word. At this point, the baud counter needs to be reset |
// to the number of CLOCKS_PER_BAUD, and zero_baud_counter set to zero. |
// |
// The logic is a bit twisted here, in that it will only check for the |
// above condition when zero_baud_counter is false--so as to make |
// certain the STOP bit is complete. |
initial zero_baud_counter = 1'b0; |
initial baud_counter = 24'h05; |
always @(posedge i_clk) |
begin |
zero_baud_counter <= (baud_counter == 24'h01); |
if (state == `TXU_IDLE) |
begin |
baud_counter <= 24'h0; |
zero_baud_counter <= 1'b1; |
if ((i_wr)&&(!r_busy)) |
begin |
baud_counter <= CLOCKS_PER_BAUD - 24'h01; |
zero_baud_counter <= 1'b0; |
end |
end else if (!zero_baud_counter) |
baud_counter <= baud_counter - 24'h01; |
else |
baud_counter <= CLOCKS_PER_BAUD - 24'h01; |
end |
endmodule |
|
/wbuart-insert.v
86,16 → 86,16
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]; |
assign o_rts_n = r_rx_data[8]; |
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 |
// Transmit hardware flow control, the cts line |
wire cts_n; |
// Set this cts value to zero 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; |
// i_cts_n pin. |
assign cts_n = i_cts_n; |
|
// |
// Then the UART transmitter |
109,7 → 109,7
wire [31:0] tx_data; |
txuart #(UART_SETUP) tx(i_clk, 1'b0, uart_setup, |
r_tx_break, r_tx_stb, r_tx_data, |
rts, o_tx, tx_busy); |
cts_n, o_tx, tx_busy); |
always @(posedge i_clk) |
if ((i_wb_stb)&&(i_wb_addr == 5'h0f)) |
begin |
121,7 → 121,7
r_tx_stb <= 1'b0; |
r_tx_data <= 8'h0; |
end |
assign tx_data = { 16'h00, rts, 3'h0, |
assign tx_data = { 16'h00, cts_n, 3'h0, |
ck_uart, o_tx, r_tx_break, tx_busy, |
r_tx_data }; |
assign tx_int = ~tx_busy; |
/wbuart.v
47,8 → 47,7
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, |
o_wb_ack, o_wb_stall, o_wb_data, |
// |
i_uart_rx, o_uart_tx, i_rts, o_cts, |
// i_uart_rts, o_uart_cts, i_uart_dtr, o_uart_dts |
i_uart_rx, o_uart_tx, i_cts_n, o_rts_n, |
// |
o_uart_rx_int, o_uart_tx_int, |
o_uart_rxfifo_int, o_uart_txfifo_int); |
77,13 → 76,13
// 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; |
// If you don't wish to use hardware flow control, just set i_cts_n to |
// 1'b0 and let the optimizer simply remove this logic. |
input i_cts_n; |
// 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 reg o_rts_n; |
output wire o_uart_rx_int, o_uart_tx_int, |
o_uart_rxfifo_int, o_uart_txfifo_int; |
|
120,15 → 119,25
|
// Here's our UART receiver. Basically, it accepts our setup wires, |
// the UART input, a clock, and a reset line, and produces outputs: |
// a stb (true when new data is ready), an 8-bit data out value |
// valid when stb is high, a break value (true during a break cond.), |
// and parity/framing error flags--also valid when stb is true. |
// a stb (true when new data is ready), and an 8-bit data out value |
// valid when stb is high. |
`ifdef USE_LITE_UART |
rxuartlite #(INITIAL_SETUP[23:0]) |
rx(i_clk, (i_rst), i_uart_rx, rx_stb, rx_uart_data); |
assign rx_break = 1'b0; |
assign rx_perr = 1'b0; |
assign rx_ferr = 1'b0; |
assign ck_uart = 1'b0; |
`else |
// The full receiver also produces a break value (true during a break |
// cond.), and parity/framing error flags--also valid when stb is true. |
rxuart #(INITIAL_SETUP) rx(i_clk, (i_rst)||(rx_uart_reset), |
uart_setup, i_uart_rx, |
rx_stb, rx_uart_data, rx_break, |
rx_perr, rx_ferr, ck_uart); |
// The real trick is ... now that we have this data, what do we do |
// The real trick is ... now that we have this extra data, what do we do |
// with it? |
`endif |
|
|
// We place it into a receiver FIFO. |
170,12 → 179,10
// 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); |
o_rts_n = ((HARDWARE_FLOW_CONTROL_PRESENT) |
&&(!uart_setup[30]) |
&&(rxf_status[(LCLLGFLEN+1):4]=={(LCLLGFLEN-2){1'b1}})); |
|
// 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 |
250,10 → 257,10
// |
// |
///////////////////////////////////////// |
wire tx_empty_n, txf_err; |
wire tx_empty_n, txf_err, tx_break; |
wire [7:0] tx_data; |
wire [15:0] txf_status; |
reg r_tx_break, txf_wb_write, tx_uart_reset; |
reg txf_wb_write, tx_uart_reset; |
reg [7:0] txf_wb_data; |
|
// Unlike the receiver which goes from RXUART -> UFIFO -> WB, the |
282,7 → 289,7
// and ... we just set the values (above) for controlling writing into |
// this. |
ufifo #(.LGFLEN(LGFLEN), .RXFIFO(0)) |
txfifo(i_clk, (r_tx_break)||(tx_uart_reset), |
txfifo(i_clk, (tx_break)||(tx_uart_reset), |
txf_wb_write, txf_wb_data, |
tx_empty_n, |
(!tx_busy)&&(tx_empty_n), tx_data, |
296,6 → 303,7
// charged. |
assign o_uart_txfifo_int = txf_status[1]; |
|
`ifndef USE_LITE_UART |
// Break logic |
// |
// A break in a UART controller is any time the UART holds the line |
304,6 → 312,7
// write unsigned characters to the interface, this will never be true |
// unless you wish it to be true. Be aware, though, writing a valid |
// value to the interface will bring it out of the break condition. |
reg r_tx_break; |
initial r_tx_break = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
310,6 → 319,10
r_tx_break <= 1'b0; |
else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we)) |
r_tx_break <= i_wb_data[9]; |
assign tx_break = r_tx_break; |
`else |
assign tx_break = 1'b0; |
`endif |
|
// TX-Reset logic |
// |
326,8 → 339,12
else |
tx_uart_reset <= 1'b0; |
|
wire rts; |
assign rts = (!HARDWARE_FLOW_CONTROL_PRESENT)||(i_rts); |
`ifdef USE_LITE_UART |
txuart #(INITIAL_SETUP[23:0]) tx(i_clk, (tx_empty_n), tx_data, |
o_uart_tx, tx_busy); |
`else |
wire cts_n; |
assign cts_n = (HARDWARE_FLOW_CONTROL_PRESENT)&&(i_cts_n); |
// 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 |
339,7 → 356,8
// starting to transmit a new byte.) |
txuart #(INITIAL_SETUP) tx(i_clk, 1'b0, uart_setup, |
r_tx_break, (tx_empty_n), tx_data, |
i_rts, o_uart_tx, tx_busy); |
cts_n, o_uart_tx, tx_busy); |
`endif |
|
// Now that we are done with the chain, pick some wires for the user |
// to read on any read of the transmit port. |
355,8 → 373,8
// whether or not we are actively transmitting. |
wire [31:0] wb_tx_data; |
assign wb_tx_data = { 16'h00, |
i_rts, txf_status[1:0], txf_err, |
ck_uart, o_uart_tx, r_tx_break, (tx_busy|txf_status[0]), |
i_cts_n, txf_status[1:0], txf_err, |
ck_uart, o_uart_tx, 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 |
.
Property changes :
Added: svn:ignore
## -0,0 +1 ##
+obj_dir