module uart_rx
#(
parameter UART_BPS = 'd9600 ,
CLK_FREQ = 'd50_000_000
)(
input wire sys_clk ,
input wire sys_rst_n ,
input wire rx ,
output reg [7:0] po_data ,
output reg po_flag
);
parameter BAUD_CNT_MAX = CLK_FREQ / UART_BPS ;
// reg define signal
reg rx_reg1 ;
reg rx_reg2 ;
reg rx_reg3 ;
reg start ;
reg work_en ;
reg [12:00] baud_cnt ;
reg bit_flag ;
reg [ 3: 0] bit_cnt ;
reg [ 7: 0] rx_data ;
reg rx_flag ;
// rx_reg1 ;rx_reg2 ;rx_reg3 ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
rx_reg1 <= 1'b1 ;
rx_reg2 <= 1'b1 ;
rx_reg3 <= 1'b1 ;
end else begin
rx_reg1 <= rx ;
rx_reg2 <= rx_reg1 ;
rx_reg3 <= rx_reg2 ;
end
end
// start ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
start <= 1'b0 ;
end else begin
if(rx_reg3 == 1'b1 && rx_reg2 == 1'b0 && bit_cnt == 4'd0) begin // 或者bit_cnt换成 work_en == 0
start <= 1'b1 ;
end else begin
start <= 1'b0 ;
end
end
end
// work_en ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
work_en <= 1'b0 ;
end else begin
if(start == 1'b1) begin
work_en <= 1'b1 ;
end else begin
if((bit_cnt == 4'd8) && (bit_flag == 1'b1)) begin
work_en <= 1'b0 ;
end else begin
work_en <= work_en ;
end
end
end
end
// [12:00] baud_cnt ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
baud_cnt <= 13'd0 ;
end else begin
if(work_en == 1'b1 && baud_cnt == BAUD_CNT_MAX - 1'b1) begin
baud_cnt <= 13'd0 ;
end else begin
if(work_en == 1'b1) begin
baud_cnt <= baud_cnt + 1'b1 ;
end else begin
baud_cnt <= 13'd0 ;
end
end
end
end
// always @(posedge sys_clk or negedge sys_rst_n) begin
// if(~sys_rst_n) begin
// baud_cnt <= 13'd0 ;
// end else begin
// if(work_en == 1'b1 && baud_cnt == BAUD_CNT_MAX - 1'b1 || work_en == 1'b0) begin
// baud_cnt <= 13'd0 ;
// end else begin
// baud_cnt <= baud_cnt + 1'b1 ;
// end
// end
// end
// bit_flag ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
bit_flag <= 1'b0 ;
end else begin
if(baud_cnt == BAUD_CNT_MAX - 1'b1) begin // 也可以写成baud_cnt == BAUD_CNT_MAX / 2 - 1'b1
bit_flag <= 1'b1 ; // 这样后面赋值时,就可以直接用bit_flag .
end else begin
bit_flag <= 1'b0 ;
end
end
end
// [ 2: 0] bit_cnt ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
bit_cnt <= 4'd0 ;
end else begin
if(bit_flag == 1'b1 && work_en == 1'b1 && bit_cnt == 4'd8) begin
bit_cnt <= 4'd0 ;
end else begin
if(bit_flag == 1'b1 && work_en == 1'b1) begin
bit_cnt <= bit_cnt + 1'b1 ;
end else begin
if(work_en == 1'b1) begin
bit_cnt <= bit_cnt ;
end else begin
bit_cnt <= 3'd0 ;
end
end
end
end
end
// [7:0] rx_data ,
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
rx_data <= 8'd0 ;
end else begin
if(bit_cnt >= 4'd1 && bit_cnt <= 4'd8 && baud_cnt == 13'd3000) begin
rx_data <= {rx_reg3, rx_data[7:1]} ;
end else begin
rx_data <= rx_data ;
end
end
end
// rx_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
rx_flag <= 1'b0 ;
end else begin
if(bit_cnt == 4'd8 && bit_flag == 1'b1) begin
rx_flag <= 1'b1 ;
end else begin
rx_flag <= 1'b0 ;
end
end
end
// output signal
// po_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
po_flag <= 1'b0 ;
end else begin
if(rx_flag == 1'b1) begin
po_flag <= 1'b1 ;
end else begin
po_flag <= 1'b0 ;
end
end
end
// po_data
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
po_data <= 8'd0 ;
end else begin
if(rx_flag == 1'b1) begin
po_data <= rx_data ;
end else begin
po_data <= 8'd0 ;
end
end
end
endmodule
module uart_tx (
input wire sys_clk ,
input wire sys_rst_n ,
input wire [7:0] pi_data ,
input wire pi_flag ,
output reg tx
);
// reg signal define
reg pi_flag_r ;
reg [7:0] pi_data_r ;
reg work_en ;
reg [12:00] baud_cnt ;
reg bit_flag ;
reg [ 3: 0] bit_cnt ;
// pi_flag_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
pi_flag_r <= 1'b0 ;
end else begin
if(pi_flag == 1'b1) begin
pi_flag_r <= 1'b1 ;
end else begin
pi_flag_r <= 1'b0 ;
end
end
end
// [7:0] pi_data_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
pi_data_r <= 1'b0 ;
end else begin
if(pi_flag == 1'b1) begin
pi_data_r <= pi_data ;
end else begin
pi_data_r <= pi_data_r ;
end
end
end
// work_en ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
work_en <= 1'b0 ;
end else begin
if(baud_cnt == 13'd5027 && bit_cnt == 4'd9) begin
work_en <= 1'b0 ;
end else begin
if(pi_flag_r == 1'b1) begin
work_en <= 1'b1 ;
end else begin
work_en <= work_en ;
end
end
end
end
// [12:00] baud_cnt ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
baud_cnt <= 13'd0 ;
end else begin
if(work_en == 1'b1 && baud_cnt == 13'd5027 || work_en == 1'b0) begin
baud_cnt <= 13'd0 ;
end else begin
if(work_en == 1'b1) begin
baud_cnt <= baud_cnt + 1'b1 ;
end else begin
baud_cnt <= 13'd0 ;
end
end
end
end
// bit_flag ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
bit_flag <= 1'b0 ;
end else begin
if(baud_cnt == 13'd5026) begin // 野火上是等于 1 .
bit_flag <= 1'b1 ;
end else begin
bit_flag <= 1'b0 ;
end
end
end
// [ 3: 0] bit_cnt ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
bit_cnt <= 4'd0 ;
end else begin
if(bit_flag == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
bit_cnt <= 4'd0 ;
end else begin
if(bit_flag == 1'b1) begin
bit_cnt <= bit_cnt + 1'b1 ;
end else begin
bit_cnt <= bit_cnt ;
end
end
end
end
// output signal
// tx
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
tx <= 1'b1 ;
end else begin
if(work_en == 1'b1 && bit_cnt == 4'd0) begin
tx <= 1'b0 ;
end else begin
if(work_en == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
tx <= 1'b1 ;
end else begin
tx <= pi_data_r[bit_cnt - 1'b1] ;
end
end
end
end
endmodule
module top_uart(
input wire sys_clk ,
input wire sys_rst_n ,
input wire rx ,
output wire tx
);
// 模块间连线
wire [7:0] po_data ;
wire po_flag ;
uart_rx uart_rx_insert_top(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.rx ( rx ) ,
.po_data ( po_data ) ,
.po_flag ( po_flag )
);
uart_tx uart_tx_insert_top(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.pi_data ( po_data ) ,
.pi_flag ( po_flag ) ,
.tx ( tx )
);
endmodule
`timescale 1ns/1ns
module test_top();
reg sys_clk ;
reg sys_rst_n ;
reg rx ;
wire tx ;
// Instantiation
top_uart top_uart_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.rx ( rx ) ,
.tx ( tx )
);
parameter CYCLE = 20 ;
task rx_bit ;
input [7:0] data ;
integer i ;
for (i = 0;i <= 9 ;i = i + 1 ) begin
case (i)
0: rx <= 1'b0 ;
1: rx <= data[i - 1];
2: rx <= data[i - 1];
3: rx <= data[i - 1];
4: rx <= data[i - 1];
5: rx <= data[i - 1];
6: rx <= data[i - 1];
7: rx <= data[i - 1];
8: rx <= data[i - 1];
9: rx <= 1'b1 ;
default: rx <= 1'b1 ;
endcase
#(CYCLE * 5207) ;
end
endtask
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
rx <= 1'b1 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 100 ) ;
rx_bit(8'd1) ;
rx_bit(8'd2) ;
rx_bit(8'd3) ;
rx_bit(8'd4) ;
rx_bit(8'd5) ;
rx_bit(8'd6) ;
rx_bit(8'd7) ;
rx_bit(8'd8) ;
rx_bit(8'd9) ;
rx_bit(8'd9) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
// initial begin
// $timeformat(-9,0,"ns",6) ;
// /* (第一个位置)
// -9 是10 的负9次方 表示纳秒
// -3 表示毫秒
// */
// /* (第二个位置)
// 0 表示,小数点后显示的位数
// */
// /* (第三个位置)
// “打印字符” 与单位相对应
// */
// /* (第四个位置)
// 6 表示 打印的最小数字字符 是6个
// */
// $monitor("@time %t:sel=%b,seg=%b,cnt_16=%b,sum_tb=%b",$time,sel,seg,cnt_16) ; // 监测函数
// end
endmodule
`timescale 1ns/1ns
module test_uart();
reg sys_clk ;
reg sys_rst_n ;
reg rx ;
wire [7:0] po_data ;
wire po_flag ;
wire tx ;
// Instantiation
uart_rx uart_rx_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.rx ( rx ) ,
.po_data ( po_data ) ,
.po_flag ( po_flag )
);
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
rx <= 1'b1 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 100 ) ;
rx <= 1'b0; // 起始位
#( CYCLE * 5207 ) ;
rx <= 1'b1; // 1
#( CYCLE * 5207 ) ;
rx <= 1'b0; // 2
#( CYCLE * 5207 ) ;
rx <= 1'b1; // 3
#( CYCLE * 5207 ) ;
rx <= 1'b0; // 4
#( CYCLE * 5207 ) ;
rx <= 1'b1; // 5
#( CYCLE * 5207 ) ;
rx <= 1'b0; // 6
#( CYCLE * 5207 ) ;
rx <= 1'b1; // 7
#( CYCLE * 5207 ) ;
rx <= 1'b0; // 8
#( CYCLE * 5207 ) ;
rx <= 1'b1; // 终止位
#( CYCLE * 5207 ) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
uart_tx uart_tx_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.pi_data ( po_data ) ,
.pi_flag ( po_flag ) ,
.tx ( tx )
);
// initial begin
// $timeformat(-9,0,"ns",6) ;
// /* (第一个位置)
// -9 是10 的负9次方 表示纳秒
// -3 表示毫秒
// */
// /* (第二个位置)
// 0 表示,小数点后显示的位数
// */
// /* (第三个位置)
// “打印字符” 与单位相对应
// */
// /* (第四个位置)
// 6 表示 打印的最小数字字符 是6个
// */
// $monitor("@time %t:sel=%b,seg=%b,cnt_16=%b,sum_tb=%b",$time,sel,seg,cnt_16) ; // 监测函数
// end
endmodule