OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.