Skip to content

Commit 536a8b8

Browse files
committed
Rewriting UART modules to SystemVerilog
1 parent b4b191c commit 536a8b8

File tree

4 files changed

+114
-8
lines changed

4 files changed

+114
-8
lines changed

UartRx.v

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
// Features early asynchronous 'busy' reset
1111

1212

13+
CAUTION !
14+
THIS CODE IS OBSOLETE NOW. PLEASE USE "uart_rx.sv" VERSION INSTEAD
15+
16+
1317
/* --- INSTANTIATION TEMPLATE BEGIN ---
1418
1519
UartRx UR1 (
@@ -85,15 +89,15 @@ always @ (posedge clk) begin
8589
end else begin
8690
rx_sample_cntr[15:0] <= rx_sample_cntr[15:0] - 1; // counting and sampling only when 'busy'
8791
end
88-
92+
8993
if (rx_do_sample) begin
9094
if (rx_data_9th_bit == 1) begin
9195
rx_busy <= 0; // early asynchronous 'busy' reset
9296
end else begin
9397
{rx_data[7:0],rx_data_9th_bit} <= {s_rxd, rx_data[7:0]};
9498
end //
9599
end // rx_do_sample
96-
100+
97101
end // ~rx_busy
98102
end // ~nrst
99103
end

UartTx.v

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
// If multiple UartTX instances should be inferred - make tx_sample_cntr logic common for all TX instances for effective chip area usage
1212

1313

14+
CAUTION !
15+
THIS CODE IS OBSOLETE NOW. PLEASE USE "uart_tx.sv" VERSION INSTEAD
16+
17+
1418
/* --- INSTANTIATION TEMPLATE BEGIN ---
1519
1620
UartTx UT1 (
@@ -69,14 +73,14 @@ always @ (posedge clk) begin
6973
tx_busy <= 1;
7074
end
7175
end else begin
72-
76+
7377
if (tx_do_sample) begin // next bit
7478
{tx_shifter[9:0],txd} <= {tx_shifter[9:0],txd} >> 1; // txd MUST change only on tx_do_sample although data may be loaded earlier
7579
if (~|tx_shifter[9:1]) begin // early asynchronous 'busy' reset
7680
tx_busy <= 0; // txd still holds data, but shifter is ready to get new info
77-
end
81+
end
7882
end // tx_do_sample
79-
83+
8084
end // ~tx_busy
8185
end // ~nrst
8286
end

UartTx_UartRx_tb.v

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55

66
// INFO --------------------------------------------------------------------------------
77
//
8-
//
8+
9+
10+
CAUTION !
11+
THIS CODE IS OBSOLETE NOW. PLEASE USE "uart_tx.sv", "uart_rx.sv" BLOCKS
12+
AND THEIR TESTBENCHES INSTEAD
13+
914

1015
`timescale 1ns / 1ps
1116

@@ -14,7 +19,7 @@ module SimWrapper();
1419
reg clk200;
1520
initial begin
1621
#0 clk200 = 1;
17-
forever
22+
forever
1823
#2.5 clk200 = ~clk200;
1924
end
2025

@@ -92,7 +97,7 @@ defparam UT1.BAUD = 100_000_000;
9297
UartRx UR1 (
9398
.clk(clk200),
9499
.nrst(nrst),
95-
100+
96101
.rx_data(),
97102
.rx_busy(),
98103
.rx_done(),

uart_tx.sv

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//------------------------------------------------------------------------------
2+
// uart_tx.sv
3+
// Konstantin Pavlov, pavlovconst@gmail.com
4+
//------------------------------------------------------------------------------
5+
6+
// INFO ------------------------------------------------------------------------
7+
// Straightforward yet simple UART transmitter implementation
8+
// for FPGA written in Verilog
9+
//
10+
// One stop bit setting is hardcoded
11+
// Features continuous data output at BAUD levels up to CLK_HZ / 2
12+
// Features early asynchronous 'busy' set and reset to gain time to prepare new data
13+
// If multiple UartTX instances should be inferred - make tx_sample_cntr logic
14+
// that is common for all TX instances for effective chip area usage
15+
16+
17+
/* --- INSTANTIATION TEMPLATE BEGIN ---
18+
19+
uart_tx #(
20+
.CLK_HZ( 200_000_000 ), // in Hertz
21+
.BAUD( 9600 ) // max. BAUD is CLK_HZ / 2
22+
) tx1 (
23+
.clk( ),
24+
.nrst( 1'b1 ),
25+
//.tx_do_sample( ),
26+
.tx_data( ),
27+
.tx_start( ),
28+
.tx_busy( ),
29+
.txd( )
30+
);
31+
32+
--- INSTANTIATION TEMPLATE END ---*/
33+
34+
35+
module uart_tx #(
36+
CLK_HZ = 200_000_000,
37+
BAUD = 9600,
38+
bit [15:0] BAUD_DIVISOR = CLK_HZ / BAUD
39+
)(
40+
input clk,
41+
input nrst,
42+
//input tx_do_sample,
43+
44+
input [7:0] tx_data,
45+
input tx_start, // write strobe
46+
output logic tx_busy = 1'b0,
47+
output logic txd = 1'b1
48+
);
49+
50+
logic [9:0] tx_shifter = '0;
51+
logic [15:0] tx_sample_cntr = '0;
52+
always @ (posedge clk) begin
53+
if( (~nrst) || (tx_sample_cntr[15:0] == '0) ) begin
54+
tx_sample_cntr[15:0] <= (BAUD_DIVISOR-1'b1);
55+
end else begin
56+
tx_sample_cntr[15:0] <= tx_sample_cntr[15:0] - 1'b1;
57+
end
58+
end
59+
60+
logic tx_do_sample;
61+
assign tx_do_sample = (tx_sample_cntr[15:0] == '0);
62+
63+
64+
always @ (posedge clk) begin
65+
if( ~nrst ) begin
66+
tx_busy <= 1'b0;
67+
tx_shifter[9:0] <= '0;
68+
txd <= 1'b1;
69+
end else begin
70+
if( ~tx_busy ) begin
71+
// asynchronous data load and 'busy' set
72+
if( tx_start ) begin
73+
tx_shifter[9:0] <= { 1'b1,tx_data[7:0],1'b0 };
74+
tx_busy <= 1'b1;
75+
end
76+
end else begin
77+
78+
if( tx_do_sample ) begin // next bit
79+
// txd MUST change only on tx_do_sample although data may be loaded earlier
80+
{ tx_shifter[9:0],txd } <= { tx_shifter[9:0],txd } >> 1;
81+
// early asynchronous 'busy' reset
82+
if( ~|tx_shifter[9:1] ) begin
83+
// txd still holds data, but shifter is ready to get new info
84+
tx_busy <= 1'b0;
85+
end
86+
end // tx_do_sample
87+
88+
end // ~tx_busy
89+
end // ~nrst
90+
end
91+
92+
endmodule
93+

0 commit comments

Comments
 (0)