OpenCores
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 17 to Rev 18
    Reverse comparison

Rev 17 → Rev 18

/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
/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;
/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))
/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
 
/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
/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.