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 17 to Rev 18
- ↔ Reverse comparison
Rev 17 → Rev 18
/trunk/bench/cpp/Makefile
76,38 → 76,41
RTLD := ../verilog |
VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"') |
VROOT := $(VERILATOR_ROOT) |
INCS := -I$(RTLD)/obj_dir/ -I/usr/share/verilator/include |
INCS := -I$(RTLD)/obj_dir/ -I$(VROOT)/include |
SOURCES := helloworld.cpp linetest.cpp uartsim.cpp uartsim.h |
VOBJDR := $(RTLD)/obj_dir |
SYSVDR := /usr/share/verilator/include |
VLIB := $(SYSVDR)/verilated.cpp $(SYSVDR)/verilated_vcd_c.cpp |
SYSVDR := $(VROOT)/include |
VSRC := verilated.cpp verilated_vcd_c.cpp |
VLIB := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(VSRC))) |
# Sources necessary to build the linetest program (rxuart-txuart test) |
LINSRCS := linetest.cpp uartsim.cpp |
LINOBJ := $(subst .cpp,.o,$(LINSRCS)) |
LINOBJS:= $(addprefix $(OBJDIR)/,$(LINOBJ)) |
LINOBJS:= $(addprefix $(OBJDIR)/,$(LINOBJ)) $(VLIB) |
# Sources necessary to build the helloworld test (txuart test) |
HLOSRCS := helloworld.cpp uartsim.cpp |
HLOOBJ := $(subst .cpp,.o,$(HLOSRCS)) |
HLOOBJS:= $(addprefix $(OBJDIR)/,$(HLOOBJ)) |
HLOOBJS:= $(addprefix $(OBJDIR)/,$(HLOOBJ)) $(VLIB) |
# Sources necessary to build the speech test (wbuart test) |
SPCHSRCS:= speechtest.cpp uartsim.cpp |
SPCHOBJ := $(subst .cpp,.o,$(SPCHSRCS)) |
SPCHOBJS:= $(addprefix $(OBJDIR)/,$(SPCHOBJ)) |
SPCHOBJS:= $(addprefix $(OBJDIR)/,$(SPCHOBJ)) $(VLIB) |
all: $(OBJDIR)/ linetest helloworld speechtest test |
|
$(OBJDIR)/: |
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi" |
|
$(OBJDIR)/uartsim.o: uartsim.cpp uartsim.h |
|
$(OBJDIR)/%.o: %.cpp |
$(mk-objdir) |
$(CXX) $(FLAGS) $(INCS) -c $< -o $@ |
|
$(OBJDIR)/%.o: $(SYSVDR)/%.cpp |
$(mk-objdir) |
$(CXX) $(FLAGS) $(INCS) -c $< -o $@ |
|
linetest: $(LINOBJS) $(VOBJDR)/Vlinetest__ALL.a |
$(CXX) $(FLAGS) $(INCS) $^ $(VLIB) -o $@ |
$(CXX) $(FLAGS) $(INCS) $^ -o $@ |
|
helloworld: $(HLOOBJS) $(VOBJDR)/Vhelloworld__ALL.a |
$(CXX) $(FLAGS) $(INCS) $^ $(VLIB) -o $@ |
$(CXX) $(FLAGS) $(INCS) $^ -o $@ |
|
# |
# The speech test program depends upon a copy of the Gettysburg Address, |
131,12 → 134,42
# Actually, we could've done this without the speech file being available, but |
# this works. |
speechtest: speech.hex $(SPCHOBJS) $(VOBJDR)/Vspeechfifo__ALL.a |
$(CXX) $(FLAGS) $(INCS) $(SPCHOBJS) $(VOBJDR)/Vspeechfifo__ALL.a $(VLIB) -o $@ |
$(CXX) $(FLAGS) $(INCS) $(SPCHOBJS) $(VOBJDR)/Vspeechfifo__ALL.a -o $@ |
|
test: linetest speechtest |
./linetest |
./speechtest |
|
# |
# The "depends" target, to know what files things depend upon. The depends |
# file itself is kept in $(OBJDIR)/depends.txt |
# |
define build-depends |
$(mk-objdir) |
@echo "Building dependency file" |
@$(CXX) $(CFLAGS) $(INCS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt |
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt |
@rm $(OBJDIR)/xdepends.txt |
endef |
|
.PHONY: depends |
depends: tags |
$(build-depends) |
|
$(OBJDIR)/depends.txt: depends |
|
# |
define mk-objdir |
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi" |
endef |
|
# |
# The "tags" target |
# |
tags: $(SOURCES) $(HEADERS) |
@echo "Generating tags" |
@ctags $(SOURCES) $(HEADERS) |
|
.PHONY: clean |
clean: |
rm -f ./linetest ./helloworld ./speechtest |
143,3 → 176,4
rm -f ./mkspeech ./speech.hex |
rm -rf $(OBJDIR)/ |
|
-include $(OBJDIR)/depends.txt |
/trunk/bench/cpp/helloworld.cpp
36,6 → 36,7
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <verilatedos.h> |
#include <stdio.h> |
#include <fcntl.h> |
#include <unistd.h> |
/trunk/bench/cpp/linetest.cpp
44,6 → 44,7
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <verilatedos.h> |
#include <stdio.h> |
#include <fcntl.h> |
#include <unistd.h> |
/trunk/bench/cpp/speech.txt
1,24 → 1,32
Four score and seven years ago our fathers brought forth on this continent, a |
new nation, conceived in Liberty, and dedicated to the proposition that all men |
are created equal. |
|===================================================================| |
| | |
| Four score and seven years ago our fathers brought forth on this | |
| continent, a new nation, conceived in Liberty, and dedicated to | |
| the proposition that all men are created equal. | |
| | |
| Now we are engaged in a great civil war, testing whether that | |
| nation, or any nation so conceived and so dedicated, can long | |
| endure. We are met on a great battle-field of that war. We have | |
| come to dedicate a portion of that field, as a final resting | |
| place for those who here gave their lives that that nation might | |
| live. It is altogether fitting and proper that we should do this. | |
| | |
| But, in a larger sense, we can not dedicate-we can not consecrate-| |
| we can not hallow-this ground. The brave men, living and dead, | |
| who struggled here, have consecrated it, far above our poor power | |
| to add or detract. The world will little note, nor long remember | |
| what we say here, but it can never forget what they did here. It | |
| is for us the living, rather, to be dedicated here to the | |
| unfinished work which they who fought here have thus far so nobly | |
| advanced. It is rather for us to be here dedicated to the great | |
| task remaining before us-that from these honored dead we take | |
| increased devotion to that cause for which they gave the last | |
| full measure of devotion-that we here highly resolve that these | |
| dead shall not have died in vain-that this nation, under God, | |
| shall have a new birth of freedom-and that government of the | |
| people, by the people, for the people, shall not perish from the | |
| earth. | |
| | |
| | |
|===================================================================| |
|
Now we are engaged in a great civil war, testing whether that nation, or any |
nation so conceived and so dedicated, can long endure. We are met on a great |
battle-field of that war. We have come to dedicate a portion of that field, as |
a final resting place for those who here gave their lives that that nation |
might live. It is altogether fitting and proper that we should do this. |
|
But, in a larger sense, we can not dedicate-we can not consecrate-we can not |
hallow-this ground. The brave men, living and dead, who struggled here, have |
consecrated it, far above our poor power to add or detract. The world will |
little note, nor long remember what we say here, but it can never forget what |
they did here. It is for us the living, rather, to be dedicated here to the |
unfinished work which they who fought here have thus far so nobly advanced. It |
is rather for us to be here dedicated to the great task remaining before |
us-that from these honored dead we take increased devotion to that cause for |
which they gave the last full measure of devotion-that we here highly resolve |
that these dead shall not have died in vain-that this nation, under God, shall |
have a new birth of freedom-and that government of the people, by the people, |
for the people, shall not perish from the earth. |
|
|
/trunk/bench/cpp/speechtest.cpp
41,6 → 41,7
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <verilatedos.h> |
#include <stdio.h> |
#include <fcntl.h> |
#include <unistd.h> |
115,7 → 116,7
tfp->open("speechtrace.vcd"); |
|
testcount = 0; |
while(testcount < baudclocks * 16 * 2048) { |
while(testcount < baudclocks * 16 * 4096) { |
// Run one tick of the clock. |
|
tb.i_clk = 1; // Positive edge |
/trunk/bench/cpp/uartsim.cpp
57,8 → 57,8
|
m_skt = socket(AF_INET, SOCK_STREAM, 0); |
if (m_skt < 0) { |
perror("Could not allocate socket: "); |
exit(-1); |
perror("ERR: Could not allocate socket: "); |
exit(EXIT_FAILURE); |
} |
|
// Set the reuse address option |
66,8 → 66,8
int optv = 1, er; |
er = setsockopt(m_skt, SOL_SOCKET, SO_REUSEADDR, &optv, sizeof(optv)); |
if (er != 0) { |
perror("SockOpt Err:"); |
exit(-1); |
perror("ERR: SockOpt Err:"); |
exit(EXIT_FAILURE); |
} |
} |
|
79,13 → 79,13
my_addr.sin_port = htons(port); |
|
if (bind(m_skt, (struct sockaddr *)&my_addr, sizeof(my_addr))!=0) { |
perror("BIND FAILED:"); |
exit(-1); |
perror("ERR: BIND FAILED:"); |
exit(EXIT_FAILURE); |
} |
|
if (listen(m_skt, 1) != 0) { |
perror("Listen failed:"); |
exit(-1); |
perror("ERR: Listen failed:"); |
exit(EXIT_FAILURE); |
} |
} |
|
131,9 → 131,7
} |
} |
|
int UARTSIM::nettick(int i_tx) { |
int o_rx = 1; |
|
void UARTSIM::check_for_new_connections(void) { |
if ((m_conrd < 0)&&(m_conwr<0)&&(m_skt>=0)) { |
// Can we accept a connection? |
struct pollfd pb; |
148,9 → 146,17
|
if (m_conrd < 0) |
perror("Accept failed:"); |
// else printf("New connection accepted!\n"); |
} |
} |
|
} |
|
int UARTSIM::nettick(int i_tx) { |
int o_rx = 1, nr = 0; |
|
check_for_new_connections(); |
|
if ((!i_tx)&&(m_last_tx)) |
m_rx_changectr = 0; |
else m_rx_changectr++; |
173,6 → 179,7
if (1 != send(m_conwr, buf, 1, 0)) { |
close(m_conwr); |
m_conrd = m_conwr = -1; |
fprintf(stderr, "Failed write, connection closed\n"); |
} |
} |
} else { |
201,7 → 208,7
perror("Polling error:"); |
if (pb.revents & POLLIN) { |
char buf[1]; |
if (1 == recv(m_conrd, buf, 1, MSG_DONTWAIT)) { |
if (1 == (nr = recv(m_conrd, buf, 1, MSG_DONTWAIT))) { |
m_tx_data = (-1<<(m_nbits+m_nparity+1)) |
// << nstart_bits |
|((buf[0]<<1)&0x01fe); |
226,6 → 233,14
m_tx_state = TXDATA; |
o_rx = 0; |
m_tx_baudcounter = m_baud_counts-1; |
} else if (nr == 0) { |
close(m_conrd); |
m_conrd = m_conwr = -1; |
// printf("Closing network connection\n"); |
} else if (nr < 0) { |
perror("O/S Read err:"); |
close(m_conrd); |
m_conrd = m_conwr = -1; |
} |
} |
} else if (m_tx_baudcounter <= 0) { |
/trunk/bench/cpp/uartsim.h
79,6 → 79,10
// related setup stuff. |
void setup_listener(const int port); |
|
// Call check_for_new_connections() to see if we can accept a new |
// network socket connection to our device |
void check_for_new_connections(void); |
|
// nettick() gets called if we are connected to a network, and |
int nettick(const int i_tx); |
// fdtick() if we are not. |
/trunk/bench/verilog/Makefile
18,7 → 18,7
## |
## // If we have a 100MHz clock, then we can set up for a 115,200 |
## // baud clock by setting i_setup to (100MHz / 115200) ~= 868. |
## // The upper bits of this number also set the protocol to |
## // The upper bits of this number also set the protocol to |
## // one stop bit, no parity, and 8 data bits. |
## assign i_setup = 30'd868; // 115,200 Baud 8N1 |
## |
58,7 → 58,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. |
## |
74,6 → 74,8
FBDIR := . |
VDIRFB:= $(FBDIR)/obj_dir |
RTLDR := ../../rtl |
VERILATOR := verilator |
VFLAGS := -Wall --MMD --trace -y ../../rtl -cc |
|
.PHONY: test testline testhello speechfifo |
test: testline testhello speechfifo |
99,7 → 101,7
$(SPEECHVFILES): speechfifo.v $(SPEECHSRCS) |
|
$(VDIRFB)/V%.cpp $(VDIRFB)/V%.h $(VDIRFB)/V%.mk: $(FBDIR)/%.v |
verilator --trace -cc -y ../../rtl $*.v |
$(VERILATOR) $(VFLAGS) $*.v |
|
$(VDIRFB)/V%__ALL.a: $(VDIRFB)/V%.mk |
cd $(VDIRFB); make -f V$*.mk |
111,3 → 113,7
rm -rf $(VDIRFB)/*.h |
rm -rf $(VDIRFB)/ |
|
DIRS := $(wildcard $(VDIRFB)/*.d) |
ifneq ($(DIRS),) |
-include $(DIRS) |
endif |
/trunk/bench/verilog/linetest.v
91,7 → 91,7
reg pwr_reset; |
initial pwr_reset = 1'b1; |
always @(posedge i_clk) |
pwr_reset = 1'b0; |
pwr_reset <= 1'b0; |
|
|
|
102,7 → 102,10
// 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. |
wire rx_stb, rx_break, rx_perr, rx_ferr, rx_ignored; |
wire rx_stb, rx_break, rx_perr, rx_ferr; |
/* verilator lint_off UNUSED */ |
wire rx_ignored; |
/* verilator lint_on UNUSED */ |
wire [7:0] rx_data; |
|
`ifdef USE_LITE_UART |
/trunk/bench/verilog/speechfifo.v
21,7 → 21,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 |
72,6 → 72,10
// i_setup, but at least it gives us something to start with/from. |
parameter INITIAL_UART_SETUP = 31'd868; |
|
// Let's set our message length, in case we ever wish to change it in |
// the future |
localparam MSGLEN=2203; |
|
// 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. |
87,11 → 91,22
reg [1:0] wb_addr; |
reg [31:0] wb_data; |
|
wire uart_stall, uart_ack; |
wire uart_stall; |
|
// We aren't using the receive interrupts, or the received data, or the |
// ready to send line, so we'll just mark them all here as ignored. |
|
/* verilator lint_off UNUSED */ |
wire uart_ack, tx_int; |
wire [31:0] uart_data; |
wire ignored_rx_int, ignored_rxfifo_int; |
wire rts_n_ignored; |
/* verilator lint_on UNUSED */ |
|
wire tx_int, txfifo_int; |
/* verilator lint_on UNUSED */ |
|
wire txfifo_int; |
|
// The next four lines create a strobe signal that is true on the first |
// clock, but never after. This makes for a decent power-on reset |
// signal. |
107,7 → 122,7
// element to a space so that if (for some reason) we broadcast past the |
// end of our message, we'll at least be sending something useful. |
integer i; |
reg [7:0] message [0:2047]; |
reg [7:0] message [0:4095]; |
initial begin |
// xx Verilator needs this file to be in the directory the file |
// is run from. For that reason, the project builds, makes, |
121,8 → 136,9
// synthesis tool can find it. |
// |
$readmemh("speech.hex", message); |
for(i=1481; i<2048; i=i+1) |
for(i=MSGLEN; i<4095; i=i+1) |
message[i] = 8'h20; |
|
// |
// The problem with the above approach is Xilinx's ISE program. |
// It's broken. It can't handle HEX files well (at all?) and |
164,8 → 180,8
// transmit next. Note, there's a clock delay between setting this |
// index and when the wb_data is valid. Hence, we set the index on |
// restart[0] to zero. |
reg [10:0] msg_index; |
initial msg_index = 11'd2040; |
reg [11:0] msg_index; |
initial msg_index = 12'h000 - 12'h8; |
always @(posedge i_clk) |
begin |
if (restart) |
220,7 → 236,7
if (restart) |
end_of_message <= 1'b0; |
else |
end_of_message <= (msg_index >= 1481); |
end_of_message <= (msg_index >= MSGLEN); |
|
// The wb_stb signal indicates that we wish to write, using the wishbone |
// to our peripheral. We have two separate types of writes. First, |
248,10 → 264,6
// 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 |
// here as ignored. |
wire ignored_rx_int, ignored_rxfifo_int; |
|
// The WBUART can handle hardware flow control signals. This test, |
// however, cannot. The reason? Simply just to keep things simple. |
// If you want to add hardware flow control to your design, simply |
259,7 → 271,7
// |
// Since this is an output only module demonstrator, what would be the |
// cts output is unused. |
wire cts_n, rts_n_ignored; |
wire cts_n; |
assign cts_n = 1'b0; |
|
// Finally--the unit under test--now that we've set up all the wires |
/trunk/doc/gpl-3.0.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/doc/spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/doc/src/spec.tex
67,6 → 67,7
with this program. If not, see \texttt{http://www.gnu.org/licenses/} for a copy. |
\end{license} |
\begin{revisionhistory} |
1.01 & 6/02/2017 & D. Gisselquist & Clarified register descriptions\\\hline |
1.0 & 2/20/2017 & D. Gisselquist & Added Hardware Flow Control\\\hline |
0.2 & 1/03/2017 & D. Gisselquist & Added test-bench information\\\hline |
0.1 & 8/26/2016 & D. Gisselquist & Initial Draft Specification\\\hline |
349,7 → 350,8
bits. Set this to one for two stop bits, or leave it at zero for a single |
stop bit. $P$ determines whether or not a parity bit is used (1~for parity, |
0~for no parity), while $F$ determines whether or not the parity is fixed. |
Tbl.~\ref{tbl:parity} lists out the various values possible here. |
Tbl.~\ref{tbl:parity} lists how $P$, $F$, and $T$ affect which parity |
is being used. |
\begin{table}\begin{center} |
\begin{tabular}{ccc|l} |
P&F&T&Setting \\\hline\hline |
364,7 → 366,7
The final portion of this register is the baud {\tt CLKS}. This is the number |
of ticks of your system clock per baud interval, |
\begin{eqnarray*} |
{\tt CLKS} &=& \frac{f_{\mbox{\tiny SYS}}}{f_{\mbox{\tiny BAUD}}}. |
{\tt CLKS} &=& \left\lfloor \frac{f_{\mbox{\tiny SYS}}}{f_{\mbox{\tiny BAUD}}} \right\rfloor. |
\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 |
/trunk/rtl/Makefile
44,6 → 44,7
CXX := g++ |
FBDIR := . |
VDIRFB:= $(FBDIR)/obj_dir |
VERILATOR := verilator |
|
.PHONY: test |
test: $(VDIRFB)/Vtxuart__ALL.a |
73,7 → 74,7
$(VDIRFB)/Vwbuart.h $(VDIRFB)/Vwbuart.cpp $(VDIRFB)/Vwbuart.mk: wbuart.v ufifo.v txuart.v rxuart.v |
|
$(VDIRFB)/V%.cpp $(VDIRFB)/V%.h $(VDIRFB)/V%.mk: $(FBDIR)/%.v |
verilator -cc $*.v |
$(VERILATOR) -Wall -cc $*.v |
|
$(VDIRFB)/V%__ALL.a: $(VDIRFB)/V%.mk |
cd $(VDIRFB); make -f V$*.mk |
/trunk/rtl/rxuart.v
122,7 → 122,9
parameter [30:0] INITIAL_SETUP = 31'd868; |
// 8 data bits, no parity, (at least 1) stop bit |
input wire i_clk, i_reset; |
/* verilator lint_off UNUSED */ |
input wire [30:0] i_setup; |
/* verilator lint_on UNUSED */ |
input wire i_uart_rx; |
output reg o_wr; |
output reg [7:0] o_data; |
/trunk/rtl/rxuartlite.v
66,7 → 66,7
output reg [7:0] o_data; |
|
|
wire [23:0] clocks_per_baud, half_baud; |
wire [23:0] half_baud; |
reg [3:0] state; |
|
assign half_baud = { 1'b0, CLOCKS_PER_BAUD[23:1] } - 24'h1; |
152,8 → 152,6
// available. |
// |
initial o_data = 8'h00; |
reg pre_wr; |
initial pre_wr = 1'b0; |
always @(posedge i_clk) |
if ((zero_baud_counter)&&(state == `RXUL_STOP)) |
begin |
166,7 → 164,7
// |
// 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 |
// we set ourselves up for CLOCKS_PER_BAUD counts between baud |
// intervals. |
always @(posedge i_clk) |
if ((zero_baud_counter)|||(state == `RXUL_IDLE)) |
/trunk/rtl/txuartlite.v
14,7 → 14,7
// 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. |
// 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 |
64,7 → 64,7
// |
// |
module txuartlite(i_clk, i_wr, i_data, o_uart_tx, o_busy); |
parameter [23:0] CLOCKS_PER_BAUD = 24'd868; |
parameter [23:0] CLOCKS_PER_BAUD = 24'd8; // 24'd868; |
input wire i_clk; |
input wire i_wr; |
input wire [7:0] i_data; |
82,7 → 82,6
|
initial r_busy = 1'b1; |
initial state = `TXUL_IDLE; |
initial lcl_data= 8'h0; |
always @(posedge i_clk) |
begin |
if (!zero_baud_counter) |
103,7 → 102,7
state <= state + 1; |
else |
state <= `TXUL_IDLE; |
end |
end |
end |
|
// o_busy |
204,5 → 203,126
else |
baud_counter <= CLOCKS_PER_BAUD - 24'h01; |
end |
|
// |
// |
// FORMAL METHODS |
// |
// |
// |
`ifdef FORMAL |
|
`ifdef TXUARTLITE |
`define ASSUME assume |
`else |
`define ASSUME assert |
`endif |
|
// Setup |
|
reg f_past_valid, f_last_clk; |
|
always @($global_clock) |
begin |
restrict(i_clk == !f_last_clk); |
f_last_clk <= i_clk; |
if (!$rose(i_clk)) |
begin |
`ASSUME($stable(i_wr)); |
`ASSUME($stable(i_data)); |
end |
end |
|
initial f_past_valid = 1'b0; |
always @(posedge i_clk) |
f_past_valid <= 1'b1; |
|
always @(posedge i_clk) |
if ((f_past_valid)&&($past(i_wr))&&($past(o_busy))) |
begin |
`ASSUME(i_wr == $past(i_wr)); |
`ASSUME(i_data == $past(i_data)); |
end |
|
// Check the baud counter |
always @(posedge i_clk) |
if (zero_baud_counter) |
assert(baud_counter == 0); |
|
always @(posedge i_clk) |
if ((f_past_valid)&&($past(baud_counter != 0))&&($past(state != `TXUL_IDLE))) |
assert(baud_counter == $past(baud_counter - 1'b1)); |
|
always @(posedge i_clk) |
if ((f_past_valid)&&(!$past(zero_baud_counter))&&($past(state != `TXUL_IDLE))) |
assert($stable(o_uart_tx)); |
|
reg [23:0] f_baud_count; |
initial f_baud_count = 1'b0; |
always @(posedge i_clk) |
if (zero_baud_counter) |
f_baud_count <= 0; |
else |
f_baud_count <= f_baud_count + 1'b1; |
|
always @(posedge i_clk) |
assert(f_baud_count < CLOCKS_PER_BAUD); |
|
always @(posedge i_clk) |
if (baud_counter != 0) |
assert(o_busy); |
|
reg [9:0] f_txbits; |
initial f_txbits = 0; |
always @(posedge i_clk) |
if (zero_baud_counter) |
f_txbits <= { o_uart_tx, f_txbits[9:1] }; |
|
reg [3:0] f_bitcount; |
initial f_bitcount = 0; |
always @(posedge i_clk) |
//if (baud_counter == CLOCKS_PER_BAUD - 24'h01) |
//f_bitcount <= f_bitcount + 1'b1; |
if ((!f_past_valid)||(!$past(f_past_valid))) |
f_bitcount <= 0; |
else if ((state == `TXUL_IDLE)&&(zero_baud_counter)) |
f_bitcount <= 0; |
else if (zero_baud_counter) |
f_bitcount <= f_bitcount + 1'b1; |
|
always @(posedge i_clk) |
assert(f_bitcount <= 4'ha); |
|
reg [7:0] f_request_tx_data; |
always @(posedge i_clk) |
if ((i_wr)&&(!o_busy)) |
f_request_tx_data <= i_data; |
|
wire [3:0] subcount; |
assign subcount = 10-f_bitcount; |
always @(posedge i_clk) |
if (f_bitcount > 0) |
assert(!f_txbits[subcount]); |
/* |
|
always @(posedge i_clk) |
if ((f_bitcount > 2)&&(f_bitcount <= 10)) |
assert(f_txbits[f_bitcount-2:0] |
== f_request_tx_data[7:(9-f_bitcount)]); |
*/ |
|
always @(posedge i_clk) |
if (f_bitcount == 4'ha) |
begin |
assert(f_txbits[8:1] == f_request_tx_data); |
assert( f_txbits[9]); |
end |
|
always @(posedge i_clk) |
assert((state <= `TXUL_STOP + 1'b1)||(state == `TXUL_IDLE)); |
// |
// |
|
`endif // FORMAL |
endmodule |
|
/trunk/rtl/ufifo.v
4,7 → 4,14
// |
// Project: wbuart32, a full featured UART with simulator |
// |
// Purpose: |
// Purpose: A synchronous data FIFO, designed for supporting the Wishbone |
// UART. Particular features include the ability to read and |
// write on the same clock, while maintaining the correct output FIFO |
// parameters. Two versions of the FIFO exist within this file, separated |
// by the RXFIFO parameter's value. One, where RXFIFO = 1, produces status |
// values appropriate for reading and checking a read FIFO from logic, |
// whereas the RXFIFO = 0 applies to writing to the FIFO from bus logic |
// and reading it automatically any time the transmit UART is idle. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
111,7 → 118,7
if (i_rst) |
will_underflow <= 1'b1; |
else if (i_wr) |
will_underflow <= (will_underflow)&&(i_rd); |
will_underflow <= 1'b0; |
else if (i_rd) |
will_underflow <= (will_underflow)||(w_last_plus_one == r_first); |
else |
125,6 → 132,7
// reg r_unfl; |
// initial r_unfl = 1'b0; |
initial r_last = 0; |
initial r_next = { {(LGFLEN-1){1'b0}}, 1'b1 }; |
always @(posedge i_clk) |
if (i_rst) |
begin |
133,7 → 141,7
// r_unfl <= 1'b0; |
end else if (i_rd) |
begin |
if ((i_wr)||(!will_underflow)) // (r_first != r_last) |
if (!will_underflow) // (r_first != r_last) |
begin |
r_last <= r_next; |
r_next <= r_last +{{(LGFLEN-2){1'b0}},2'b10}; |
176,10 → 184,10
r_empty_n <= 1'b0; |
else casez({i_wr, i_rd, will_underflow}) |
3'b00?: r_empty_n <= (r_first != r_last); |
3'b11?: r_empty_n <= (r_first != r_last); |
3'b010: r_empty_n <= (r_first != w_last_plus_one); |
3'b10?: r_empty_n <= 1'b1; |
3'b010: r_empty_n <= (r_first != w_last_plus_one); |
// 3'b001: r_empty_n <= 1'b0; |
3'b110: r_empty_n <= (r_first != r_last); |
3'b111: r_empty_n <= 1'b1; |
default: begin end |
endcase |
|
194,7 → 202,13
// |
// Adjust for these differences here. |
reg [(LGFLEN-1):0] r_fill; |
initial r_fill = 0; |
generate |
if (RXFIFO != 0) |
initial r_fill = 0; |
else |
initial r_fill = -1; |
endgenerate |
|
always @(posedge i_clk) |
if (RXFIFO!=0) begin |
// Calculate the number of elements in our FIFO |
204,9 → 218,10
// another context. |
if (i_rst) |
r_fill <= 0; |
else case({(i_wr)&&(!will_overflow), (i_rd)&&(!will_underflow)}) |
2'b01: r_fill <= r_first - r_next; |
2'b10: r_fill <= r_first - r_last + 1'b1; |
else casez({(i_wr), (!will_overflow), (i_rd)&&(!will_underflow)}) |
3'b0?1: r_fill <= r_first - r_next; |
3'b110: r_fill <= r_first - r_last + 1'b1; |
3'b1?1: r_fill <= r_first - r_last; |
default: r_fill <= r_first - r_last; |
endcase |
end else begin |
215,10 → 230,10
// not the fill, but (SIZE-1)-fill. |
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; |
else casez({i_wr, (!will_overflow), (i_rd)&&(!will_underflow)}) |
3'b0?1: r_fill <= r_fill + 1'b1; |
3'b110: r_fill <= r_fill - 1'b1; |
default: r_fill <= r_fill; |
endcase |
end |
|
228,6 → 243,7
wire [3:0] lglen; |
assign lglen = LGFLEN; |
|
wire w_half_full; |
wire [9:0] w_fill; |
assign w_fill[(LGFLEN-1):0] = r_fill; |
generate if (LGFLEN < 10) |
234,7 → 250,6
assign w_fill[9:(LGFLEN)] = 0; |
endgenerate |
|
wire w_half_full; |
assign w_half_full = r_fill[(LGFLEN-1)]; |
|
assign o_status = { |
257,5 → 272,103
}; |
|
assign o_empty_n = r_empty_n; |
|
|
// |
// |
// |
// FORMAL METHODS |
// |
// |
// |
`ifdef FORMAL |
|
`ifdef UFIFO |
`define ASSUME assume |
`else |
`define ASSUME assert |
`endif |
|
// |
// Assumptions about our input(s) |
// |
// |
reg f_past_valid, f_last_clk; |
|
initial restrict(i_rst); |
|
always @($global_clock) |
begin |
restrict(i_clk == !f_last_clk); |
f_last_clk <= i_clk; |
if (!$rose(i_clk)) |
begin |
`ASSUME($stable(i_rst)); |
`ASSUME($stable(i_wr)); |
`ASSUME($stable(i_data)); |
`ASSUME($stable(i_rd)); |
end |
end |
|
// |
// Underflows are a very real possibility, should the user wish to |
// read from this FIFO while it is empty. Our parent module will need |
// to deal with this. |
// |
// always @(posedge i_clk) |
// `ASSUME((!will_underflow)||(!i_rd)||(i_rst)); |
// |
// Assertions about our outputs |
// |
// |
|
initial f_past_valid = 1'b0; |
always @(posedge i_clk) |
f_past_valid <= 1'b1; |
|
wire [(LGFLEN-1):0] f_fill, f_next, f_empty; |
assign f_fill = r_first - r_last; |
assign f_empty = {(LGFLEN){1'b1}} -f_fill; |
assign f_next = r_last + 1'b1; |
always @(posedge i_clk) |
begin |
if (RXFIFO) |
assert(f_fill == r_fill); |
else |
assert(f_empty== r_fill); |
if (f_fill == 0) |
begin |
assert(will_underflow); |
assert(!o_empty_n); |
end else begin |
assert(!will_underflow); |
assert(o_empty_n); |
end |
|
if (f_fill == {(LGFLEN){1'b1}}) |
assert(will_overflow); |
else |
assert(!will_overflow); |
|
assert(r_next == f_next); |
end |
|
always @(posedge i_clk) |
if (f_past_valid) |
begin |
if ($past(i_rst)) |
assert(!o_err); |
else begin |
// No underflow detection in this core |
// |
// if (($past(i_rd))&&($past(r_fill == 0))) |
// assert(o_err); |
// |
// We do, though, have overflow detection |
if (($past(i_wr))&&(!$past(i_rd)) |
&&($past(will_overflow))) |
assert(o_err); |
end |
end |
|
`endif |
endmodule |
/trunk/rtl/wbuart.v
64,9 → 64,10
// |
input wire i_clk, i_rst; |
// Wishbone inputs |
input wire i_wb_cyc, i_wb_stb, i_wb_we; |
input wire i_wb_cyc; // We ignore CYC for efficiency |
input wire i_wb_stb, i_wb_we; |
input wire [1:0] i_wb_addr; |
input wire [31:0] i_wb_data; |
input wire [31:0] i_wb_data; // and only use 30 lines here |
output reg o_wb_ack; |
output wire o_wb_stall; |
output reg [31:0] o_wb_data; |
95,7 → 96,8
// baud rate are all captured within this uart_setup register. |
// |
reg [30:0] uart_setup; |
initial uart_setup = INITIAL_SETUP; |
initial uart_setup = INITIAL_SETUP |
| ((HARDWARE_FLOW_CONTROL_PRESENT==1'b0)? 31'h40000000 : 0); |
always @(posedge i_clk) |
// Under wishbone rules, a write takes place any time i_wb_stb |
// is high. If that's the case, and if the write was to the |
180,11 → 182,14
// 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 |
// time we set this--thus we need to set it to one, one character before |
// necessary). |
wire [(LCLLGFLEN-1):0] check_cutoff; |
assign check_cutoff = -3; |
always @(posedge i_clk) |
o_rts_n = ((HARDWARE_FLOW_CONTROL_PRESENT) |
o_rts_n <= ((HARDWARE_FLOW_CONTROL_PRESENT) |
&&(!uart_setup[30]) |
&&(rxf_status[(LCLLGFLEN+1):4]=={(LCLLGFLEN-2){1'b1}})); |
&&(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 |
418,4 → 423,10
// set this value to zero. |
assign o_wb_stall = 1'b0; |
|
// Make verilator happy |
// verilator lint_off UNUSED |
wire [33:0] unused; |
assign unused = { i_rst, i_wb_cyc, i_wb_data }; |
// verilator lint_on UNUSED |
|
endmodule |