基于FPGA的UART发送设计
uart_tx模块的时序图
从上一篇文章中,我们已经学习了uart_rx的设计,也已经附上了详细的代码,详细同学们已经学会了该模块的设计。这篇文章我们主要介绍uart_tx模块的设计,与上篇文章相同,我们将先给出模块的时序图,再给出相应的代码,最后给出模块的测试代码。uart_tx模块的时序图如下:
uart_tx模块的代码
这里没有什么特别解释,同学们结合时序图与代码肯定可以看懂。这里直接上代码:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : uart_tx.v
// Create Time : 2020-01-04 14:20:35
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module uart_tx(
input sclk ,
input rst_n ,
input [ 7:0] pi_data ,
input fifo_empty ,
output reg rd_en ,
output reg tx
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter BAUD_CNT = 433 ;
reg [ 7:0] pi_data_r ;
reg rd_en_r ;
reg tx_flag ;
reg [14:0] cnt_baud ;
reg bit_flag ;
reg [ 3:0] bit_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
pi_data_r <= 8'd0;
else if(rd_en)
pi_data_r <= pi_data;
else
pi_data_r <= pi_data_r;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_en_r <= 1'b0;
else if(fifo_empty == 1'b0 && tx_flag == 1'b0)
rd_en_r <= 1'b1;
else
rd_en_r <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_en <= 1'b0;
else if(rd_en_r == 1'b1 && tx_flag == 1'b0)
rd_en <= 1'b1;
else
rd_en <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
tx_flag <= 1'b0;
else if(rd_en_r == 1'b1)
tx_flag <= 1'b1;
else if(bit_flag == 1'b1 && bit_cnt == 4'd9)
tx_flag <= 1'b0;
else
tx_flag <= tx_flag;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_baud <= 15'd0;
else if(tx_flag == 1'b0 || cnt_baud == BAUD_CNT)
cnt_baud <= 15'd0;
else if(tx_flag == 1'b1)
cnt_baud <= cnt_baud + 1'b1;
else
cnt_baud <= cnt_baud;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
bit_flag <= 1'b0;
else if(cnt_baud == BAUD_CNT-1)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
bit_cnt <= 4'd0;
else if(bit_flag == 1'b1 && bit_cnt == 4'd9)
bit_cnt <= 4'd0;
else if(bit_flag == 1'b1)
bit_cnt <= bit_cnt + 1'b1;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
tx <= 1'b1;
else if(bit_flag == 1'b1 && bit_cnt <= 4'd7)
tx <= pi_data_r[bit_cnt];
else if(bit_cnt == 4'd0 && tx_flag == 1'b1)
tx <= 1'b0;
else if(bit_cnt == 4'd9 && tx_flag == 1'b1)
tx <= 1'b1;
endmodule
该模块所采用的方法同样是线性序列机的方法,这里不再多说。
uart_tx测试模块的代码
为了方便大家调试,uart_tx模块的测试代码如下:
`timescale 1ns / 1ps
`define CLOCK 20
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : uart_tx_tb.v
// Create Time : 2020-01-04 14:54:40
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module uart_tx_tb();
reg sclk ;
reg rst_n ;
reg [ 7:0] pi_data ;
wire rd_en ;
wire tx ;
initial begin
sclk <= 1'b0;
rst_n = 1'b0;
#(100*`CLOCK)
rst_n = 1'b1;
end
always #(`CLOCK/2) sclk <= ~sclk;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
pi_data <= 8'd0;
else if(rd_en == 1'b1)
pi_data <= pi_data + 1'b1;
else
pi_data <= pi_data;
uart_tx uart_tx_inst(
.sclk (sclk ),
.rst_n (rst_n ),
.pi_data (pi_data ),
.fifo_empty (1'b0 ),
.rd_en (rd_en ),
.tx (tx )
);
endmodule
相信大家从上面的三个材料中肯定可以学会uart_tx模块的写法。
结束语
对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
来源:CSDN
作者:朽月
链接:https://blog.csdn.net/zhangningning1996/article/details/103836798