URL
https://opencores.org/ocsvn/wbuart32/wbuart32/trunk
Subversion Repositories wbuart32
Compare Revisions
- This comparison shows the changes necessary to convert path
/wbuart32
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/trunk/bench/cpp/helloworld.cpp
44,6 → 44,7
#include <sys/types.h> |
#include <signal.h> |
#include "verilated.h" |
#include "verilated_vcd_c.h" |
#include "Vhelloworld.h" |
#include "uartsim.h" |
|
52,21 → 53,42
Vhelloworld tb; |
UARTSIM *uart; |
int port = 0; |
unsigned setup = 25, testcount = 0; |
unsigned setup = 868, clocks = 0, baudclocks; |
|
tb.i_setup = setup; |
uart = new UARTSIM(port); |
uart->setup(tb.i_setup); |
baudclocks = tb.i_setup & 0xfffffff; |
|
while(testcount++ < 0x7f000000) { |
#define VCDTRACE |
#ifdef VCDTRACE |
Verilated::traceEverOn(true); |
VerilatedVcdC* tfp = new VerilatedVcdC; |
tb.trace(tfp, 99); |
tfp->open("helloworld.vcd"); |
#define TRACE_POSEDGE tfp->dump(10*clocks) |
#define TRACE_NEGEDGE tfp->dump(10*clocks+5) |
#define TRACE_CLOSE tfp->close() |
#else |
#define TRACE_POSEDGE |
#define TRACE_NEGEDGE |
#define TRACE_CLOSE |
#endif |
|
clocks = 0; |
while(clocks < 16*32*baudclocks) { |
|
tb.i_clk = 1; |
tb.eval(); |
TRACE_POSEDGE; |
tb.i_clk = 0; |
tb.eval(); |
TRACE_NEGEDGE; |
|
(*uart)(tb.o_uart_tx); |
clocks++; |
} |
|
TRACE_CLOSE; |
printf("\n\nSimulation complete\n"); |
} |
/trunk/bench/verilog/echotest.v
0,0 → 1,138
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: echotest.v |
// |
// Project: wbuart32, a full featured UART with simulator |
// |
// Purpose: To test that the txuart and rxuart modules work properly, by |
// echoing the input directly to the output. |
// |
// This module may be run as either a DUMBECHO, simply forwarding the input |
// wire to the output with a touch of clock in between, or it can run as |
// a smarter echo routine that decodes text before returning it. The |
// difference depends upon whether or not OPT_DUMBECHO is defined, as |
// discussed below. |
// |
// With some modifications (discussed below), this RTL should be able to |
// run as a top-level testing file, requiring only the transmit and receive |
// UART pins and the clock to work. |
// |
// DON'T FORGET TO TURN OFF HARDWARE FLOW CONTROL! ... or this'll never |
// work. If you want to run with hardware flow control on, add another |
// wire to this module in order to set o_cts to 1'b1. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, 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 |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
// Uncomment the next line defining OPT_DUMBECHO in order to test the wires |
// and external functionality of any UART, independent of the UART protocol. |
// |
`define OPT_DUMBECHO |
// |
// |
// Uncomment the next line if you want this program to work as a standalone |
// (not verilated) RTL "program" to test your UART. You'll also need to set |
// your setup condition properly, though. I recommend setting it to the |
// ratio of your onboard clock to your desired baud rate. For more information |
// about how to set this, please see the specification. |
// |
`define OPT_STANDALONE |
// |
module echotest(i_clk, |
`ifndef OPT_STANDALONE |
i_setup, |
`endif |
i_uart_rx, o_uart_tx); |
input i_clk; |
`ifndef OPT_STANDALONE |
input [29:0] i_setup; |
`endif |
input i_uart_rx; |
output wire o_uart_tx; |
|
`ifdef OPT_DUMBECHO |
reg r_uart_tx; |
|
initial r_uart_tx = 1'b1; |
always @(posedge i_clk) |
r_uart_tx <= i_uart_rx; |
assign o_uart_tx = r_uart_tx; |
`else |
// This is the "smart" echo verion--one that decodes, and then |
// re-encodes, values over the UART. There is a risk, though, doing |
// things in this manner that the receive UART might run *just* a touch |
// faster than the transmitter, and hence drop a bit every now and |
// then. Hence, it works nicely for hand-testing, but not as nicely |
// for high-speed UART testing. |
|
|
|
// If i_setup isnt set up as an input parameter, it needs to be set. |
// We do so here, to a setting appropriate to create a 115200 Baud |
// comms system from a 100MHz clock. This also sets us to an 8-bit |
// data word, 1-stop bit, and no parity. |
// |
// This code only applies if OPT_DUMBECHO is not defined. |
`ifdef OPT_STANDALONE |
wire [29:0] i_setup; |
assign i_setup = 30'd868; // 115200 Baud, if clk @ 100MHz |
`endif |
|
// Create a reset line that will always be true on a power on reset |
reg pwr_reset; |
initial pwr_reset = 1'b1; |
always @(posedge i_clk) |
pwr_reset = 1'b0; |
|
|
|
// The UART Receiver |
// |
// This is where everything begins, by reading data from the UART. |
// |
// Data (rx_data) is present when rx_stb is true. Any parity or |
// frame errors will also be valid at that time. Finally, we'll ignore |
// errors, and even the clocked uart input distributed from here. |
// |
// This code only applies if OPT_DUMBECHO is not defined. |
wire rx_stb, rx_break, rx_perr, rx_ferr, rx_ignored; |
wire [7:0] rx_data; |
|
rxuart receiver(i_clk, pwr_reset, i_setup, i_uart_rx, rx_stb, rx_data, |
rx_break, rx_perr, rx_ferr, rx_ignored); |
|
wire tx_busy; |
txuart transmitter(i_clk, pwr_reset, i_setup, rx_break, |
rx_stb, rx_data, o_uart_tx, tx_busy); |
|
`endif |
|
endmodule |
|
/trunk/bench/verilog/speechfifo.v
61,20 → 61,23
input i_clk; |
output wire o_uart_tx; |
|
// Here we set i_setup to something appropriate to create a 115200 Baud |
// UART system from a 100MHz clock. This also sets us to an 8-bit data |
// word, 1-stop bit, and no parity. This will be overwritten by |
// i_setup, but at least it gives us something to start with/from. |
parameter INITIAL_UART_SETUP = 30'd868; |
|
// The i_setup wires are input when run under Verilator, but need to |
// be set internally if this is going to run as a standalone top level |
// test configuration. |
`ifdef OPT_STANDALONE |
wire [29:0] i_setup; |
|
// Here we set i_setup to something appropriate to create a 115200 Baud |
// UART system from a 100MHz clock. This also sets us to an 8-bit data |
// word, 1-stop bit, and no parity. |
assign i_setup = 30'd868; |
assign i_setup = INITIAL_UART_SETUP; |
`else |
input [29:0] i_setup; |
`endif |
|
reg restart; |
reg wb_stb; |
reg [1:0] wb_addr; |
reg [31:0] wb_data; |
101,9 → 104,9
integer i; |
reg [7:0] message [0:2047]; |
initial begin |
for(i=0; i<2048; i=i+1) |
$readmemh("speech.hex",message); |
for(i=1481; i<2048; i=i+1) |
message[i] = 8'h20; |
$readmemh("speech.hex",message); |
end |
|
// Let's keep track of time, and send our message over and over again. |
121,12 → 124,9
// let's build a set of signals that we can use to get things started |
// again. This will be the restart signal. On this signal, we just |
// restart everything. |
reg restart; |
initial restart = 0; |
always @(posedge i_clk) |
begin |
restart <= (restart_counter == 0); |
end |
|
// Our message index. This is the address of the character we wish to |
// transmit next. Note, there's a clock delay between setting this |
175,6 → 175,21
else // if (!uart_stall)?? |
wb_addr <= 2'b11; |
|
// Knowing when to stop sending the speech is important, but depends |
// upon an 11 bit comparison. Since FPGA logic is best measured by the |
// number of inputs to an always block, we pull those 11-bits out of |
// the always block for wb_stb, and place them here on the clock prior. |
// If end_of_message is true, then we need to stop transmitting, and |
// wait for the next (restart) to get us started again. We set that |
// flag hee. |
reg end_of_message; |
initial end_of_message = 1'b1; |
always @(posedge i_clk) |
if (restart) |
end_of_message <= 1'b0; |
else |
end_of_message <= (msg_index >= 1481); |
|
// The wb_stb signal indicates that we wish to write, using the wishbone |
// to our peripheral. We have two separate types of writes. First, |
// we wish to write our setup. Then we want to drop STB and write |
184,14 → 199,26
initial wb_stb = 1'b0; |
always @(posedge i_clk) |
if (restart) |
// Start sending to the UART on a reset. The first |
// thing we'll send will be the configuration, but |
// that's done elsewhere. This just starts up the |
// writes to the peripheral wbuart. |
wb_stb <= 1'b1; |
else if (msg_index >= 1481) |
else if (end_of_message) |
// Stop transmitting when we get to the end of our |
// message. |
wb_stb <= 1'b0; |
else if (tx_int) |
// If we aren't at the end of the message, and tx_int |
// tells us the FIFO is empty, then start writing into |
// the FIFO> |
wb_stb <= 1'b1; |
else if (txfifo_int) |
// If we are writing into the FIFO, and it's less than |
// half full (i.e. txfifo_int is true) then keep going. |
wb_stb <= wb_stb; |
else |
// But once the FIFO gets to half full, stop. |
wb_stb <= 1'b0; |
|
// We aren't using the receive interrupts, so we'll just mark them |
200,7 → 227,7
|
// Finally--the unit under test--now that we've set up all the wires |
// to run/test it. |
wbuart #(30'h868) |
wbuart #(INITIAL_UART_SETUP) |
wbuarti(i_clk, pwr_reset, |
wb_stb, wb_stb, 1'b1, wb_addr, wb_data, |
uart_stall, uart_ack, uart_data, |
/trunk/doc/spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/doc/src/spec.tex
210,7 → 210,8
|
Finally, there are a series of example files found in the bench/verilog |
directory. {\tt helloworld.v} presents an example of a simple UART transmitter |
sending the ``Hello, World \\r\\n'' message over and over again. This example |
sending the ``Hello, World {\textbackslash}r{\textbackslash}n'' message over |
and over again. This example |
uses only the {\tt txuart.v} module, and can be simulated in Verilator. |
A second test file, {\tt linetest.v}, works by waiting for a line of data to be |
received, after which it parrots that line back to the terminal. This tests |
351,6 → 352,19
\end{tabular}\caption{Parity setup}\label{tbl:parity} |
\end{center}\end{table} |
|
The final portion of this register is the baud {\tt CLKS}. This is the number |
of ticks of your ssytem clock per baud interval, |
\begin{eqnarray*} |
{\tt CLKS} &=& \frac{f_{\mbox{\tiny SYS}}}{f_{\mbox{\tiny BAUD}}}. |
\end{eqnarray*} |
Rounding to the nearest integer is recommended. Hence, if you have a system |
clock of 100~MHz and wish to achieve 115,200~Baud, you would set {\tt CLKS} to |
\begin{eqnarray*} |
{\tt CLKS}_{\tiny{\tt Example}} &=& \frac{100 \cdot 10^6}{115200} |
\frac{\mbox{Clocks per Second}}{\mbox{Baud Intervals per Second}} |
\approx 868 \mbox{ Clocks per Baud Interval} |
\end{eqnarray*} |
|
Changes to this setup register will take place in the transmitter as soon as |
the transmitter is idle and ready to accept another byte. |
|
/trunk/rtl/txuart.v
116,7 → 116,8
|
wire [27:0] clocks_per_baud, break_condition; |
wire [1:0] data_bits; |
wire use_parity, parity_even, dblstop, fixd_parity; |
wire use_parity, parity_even, dblstop, fixd_parity, |
fixdp_value; |
reg [29:0] r_setup; |
assign clocks_per_baud = { 4'h0, r_setup[23:0] }; |
assign break_condition = { r_setup[23:0], 4'h0 }; |
125,6 → 126,7
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; |
131,7 → 133,6
reg [7:0] lcl_data; |
reg calc_parity, r_busy, zero_baud_counter; |
|
initial r_setup = INITIAL_SETUP; |
initial o_uart_tx = 1'b1; |
initial r_busy = 1'b1; |
initial state = `TXU_IDLE; |
142,18 → 143,13
begin |
if (i_reset) |
begin |
o_uart_tx <= 1'b1; |
r_busy <= 1'b1; |
state <= `TXU_IDLE; |
lcl_data <= 8'h0; |
calc_parity <= 1'b0; |
end else if (i_break) |
begin |
o_uart_tx <= 1'b0; |
state <= `TXU_BREAK; |
calc_parity <= 1'b0; |
r_busy <= 1'b1; |
end else if (~zero_baud_counter) |
end else if (!zero_baud_counter) |
begin // r_busy needs to be set coming into here |
r_busy <= 1'b1; |
end else if (state == `TXU_BREAK) |
160,16 → 156,10
begin |
state <= `TXU_IDLE; |
r_busy <= 1'b1; |
o_uart_tx <= 1'b1; |
calc_parity <= 1'b0; |
end else if (state == `TXU_IDLE) // STATE_IDLE |
begin |
// baud_counter <= 0; |
r_setup <= i_setup; |
calc_parity <= 1'b0; |
if ((i_wr)&&(~r_busy)) |
if ((i_wr)&&(!r_busy)) |
begin // Immediately start us off with a start bit |
o_uart_tx <= 1'b0; |
r_busy <= 1'b1; |
case(data_bits) |
2'b00: state <= `TXU_BIT_ZERO; |
177,13 → 167,8
2'b10: state <= `TXU_BIT_TWO; |
2'b11: state <= `TXU_BIT_THREE; |
endcase |
lcl_data <= i_data; |
// baud_counter <= clocks_per_baud-28'h01; |
end else begin // Stay in idle |
o_uart_tx <= 1'b1; |
r_busy <= 0; |
// lcl_data is irrelevant |
// state <= state; |
end |
end else begin |
// One clock tick in each of these states ... |
191,32 → 176,22
r_busy <= 1'b1; |
if (state[3] == 0) // First 8 bits |
begin |
o_uart_tx <= lcl_data[0]; |
calc_parity <= calc_parity ^ lcl_data[0]; |
if (state == `TXU_BIT_SEVEN) |
state <= (use_parity)?`TXU_PARITY:`TXU_STOP; |
else |
state <= state + 1; |
lcl_data <= { 1'b0, lcl_data[7:1] }; |
end else if (state == `TXU_PARITY) |
begin |
state <= `TXU_STOP; |
if (fixd_parity) |
o_uart_tx <= parity_even; |
else |
o_uart_tx <= calc_parity^((parity_even)? 1'b1:1'b0); |
end else if (state == `TXU_STOP) |
begin // two stop bit(s) |
o_uart_tx <= 1'b1; |
if (dblstop) |
state <= `TXU_SECOND_STOP; |
else |
state <= `TXU_IDLE; |
calc_parity <= 1'b0; |
end else // `TXU_SECOND_STOP and default: |
begin |
state <= `TXU_IDLE; // Go back to idle |
o_uart_tx <= 1'b1; |
// Still r_busy, since we need to wait |
// for the baud clock to finish counting |
// out this last bit. |
224,9 → 199,129
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); |
|
|
// r_setup |
// |
// Our setup register. Accept changes between any pair of transmitted |
// words. The register itself has many fields to it. These are |
// 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; |
always @(posedge i_clk) |
if (state == `TXU_IDLE) |
r_setup <= i_setup; |
|
// 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. |
always @(posedge i_clk) |
if (!r_busy) |
lcl_data <= i_data; |
else if (zero_baud_counter) |
lcl_data <= { 1'b0, 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. |
// |
// Ok, that said, our rules are: |
// 1'b0 on any break condition |
// 1'b0 on a start bit (IDLE, write, and not busy) |
// lcl_data[0] during any data transfer, but only at the baud |
// change |
// PARITY -- During the parity bit. This depends upon whether or |
// not the parity bit is fixed, then what it's fixed to, |
// or changing, and hence what it's calculated value is. |
// 1'b1 at all other times (stop bits, idle, etc) |
always @(posedge i_clk) |
if (i_reset) |
o_uart_tx <= 1'b1; |
else if ((i_break)||((i_wr)&&(!r_busy))) |
o_uart_tx <= 1'b0; |
else if (zero_baud_counter) |
casez(state) |
4'b0???: o_uart_tx <= lcl_data[0]; |
`TXU_PARITY: o_uart_tx <= calc_parity; |
default: o_uart_tx <= 1'b1; |
endcase |
|
|
// calc_parity |
// |
// Calculate the parity to be placed into the parity bit. If the |
// parity is fixed, then the parity bit is given by the fixed parity |
// value (r_setup[24]). Otherwise the parity is given by the GF2 |
// sum of all the data bits (plus one for even parity). |
always @(posedge i_clk) |
if (fixd_parity) |
calc_parity <= fixdp_value; |
else if (zero_baud_counter) |
begin |
if (state[3] == 0) // First 8 bits of msg |
calc_parity <= calc_parity ^ lcl_data[0]; |
else |
calc_parity <= parity_even; |
end else if (!r_busy) |
calc_parity <= parity_even; |
|
|
// 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 = 28'h05; |
always @(posedge i_clk) |
237,17 → 332,21
// Give ourselves 16 bauds before being ready |
baud_counter <= break_condition; |
zero_baud_counter <= 1'b0; |
end else if (~zero_baud_counter) |
end else if (!zero_baud_counter) |
baud_counter <= baud_counter - 28'h01; |
else if (state == `TXU_BREAK) |
// Give us two stop bits before becoming available |
// Give us four idle baud intervals before becoming |
// available |
baud_counter <= clocks_per_baud<<2; |
else if (state == `TXU_IDLE) |
begin |
if((i_wr)&&(~r_busy)) |
baud_counter <= 28'h0; |
zero_baud_counter <= 1'b1; |
if ((i_wr)&&(!r_busy)) |
begin |
baud_counter <= clocks_per_baud - 28'h01; |
else |
zero_baud_counter <= 1'b1; |
zero_baud_counter <= 1'b0; |
end |
end else |
baud_counter <= clocks_per_baud - 28'h01; |
end |
/trunk/rtl/ufifo.v
51,13 → 51,13
localparam FLEN=(1<<LGFLEN); |
|
reg [(BW-1):0] fifo[0:(FLEN-1)]; |
reg [(LGFLEN-1):0] r_first, r_last; |
reg [(LGFLEN-1):0] r_first, r_last, r_next; |
|
wire [(LGFLEN-1):0] w_first_plus_one, w_first_plus_two, |
w_last_plus_one; |
assign w_first_plus_two = r_first + {{(LGFLEN-2){1'b0}},2'b10}; |
assign w_first_plus_one = r_first + {{(LGFLEN-1){1'b0}},1'b1}; |
assign w_last_plus_one = r_last + {{(LGFLEN-1){1'b0}},1'b1}; |
assign w_last_plus_one = r_next; // r_last + 1'b1; |
|
reg will_overflow; |
initial will_overflow = 1'b0; |
120,17 → 120,20
always @(posedge i_clk) |
if (i_rst) |
begin |
r_last <= { (LGFLEN){1'b0} }; |
r_last <= 0; |
r_next <= { {(LGFLEN-1){1'b0}}, 1'b1 }; |
r_unfl <= 1'b0; |
end else if (i_rd) |
begin |
if ((i_wr)||(!will_underflow)) // (r_first != r_last) |
r_last <= w_last_plus_one; |
begin |
r_last <= r_next; |
r_next <= r_last +{{(LGFLEN-2){1'b0}},2'b10}; |
// Last chases first |
// Need to be prepared for a possible two |
// reads in quick succession |
// o_data <= fifo[r_last+1]; |
else |
end else |
r_unfl <= 1'b1; |
end |
|
138,7 → 141,7
always @(posedge i_clk) |
fifo_here <= fifo[r_last]; |
always @(posedge i_clk) |
fifo_next <= fifo[r_last+{{(LGFLEN-1){1'b0}},1'b1}]; |
fifo_next <= fifo[r_next]; |
always @(posedge i_clk) |
r_data <= i_data; |
|
173,7 → 176,7
if (i_rst) |
r_fill <= 0; |
else if ((i_rd)&&(!i_wr)) |
r_fill <= r_first - r_last - 1'b1; |
r_fill <= r_first - r_next; |
else if ((!i_rd)&&(i_wr)) |
r_fill <= r_first - r_last + 1'b1; |
else |
/trunk/rtl/wbuart.v
243,7 → 243,7
txf_wb_write, txf_wb_data, |
(~tx_busy)&&(tx_empty_n), tx_data, |
tx_empty_n, txf_half_full, txf_status, txf_err); |
// Let's grab two interrupts from the FIFO for the CPU. |
// 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 second will be true any time the FIFO is less than half |