第一部分为uart串口通信的接收部分,用pc端虚拟串口来对其发送数据。
第三部分为uart串口通信的发送部分,用此部分对pc端虚拟串口发送数据。
第二部分loop,处理数据,形成回环,使发送部分有数据来源,以此来保证实验的完成。
串口接收:
输入: sys_clk、sys_rst_n、uart_rxd(数据)。
输出: uart_data(数据)、uart_done(状态标志)。
reg: rx_data(寄存数据)、rx_cnt(帧计数)、clk_cnt(clk计数)、uart_rxd_d0\d1(抓取边沿)、rx_flag。
wire:start_flag。
串口发送:
输入: sys_clk、sys_rst_n、uart_din、uart_en(使能)。
输出: uart_txd(数据)、uart_tx_busy(状态标志)。
reg: tx_data(寄存数据)、tx_cnt(帧计数)、clk_cnt(clk计数)、uart_en_d0\d1(抓取边沿)、tx_flag。
wire: en_flag。
loop:
输入: sys_clk、sys_rst_n、recv_done(接收端状态)、recv_data(数据)、tx_busy(发送端状态)。
输出: send_en(发送使能)、send_data(数据)。
reg: tx_ready(准备阶段为1,使能为0,此时使recv_data等于send_data)、uart_done_d0\d1(抓取边沿)。
wire: recv_done_flag。
(1)约定波特率,clk频率除以波特率为一帧所包含的时钟个数。
parameter CLK_FREQ=50000000;
parameter UART_BPS=115200;
localparam BPS_cnt=CLK_FREQ/UART_BPS;
(2)抓取边沿。
assign start_flag=~uart_rxd_d0 & uart_rxd_d1;
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_rxd_d0<=1'b0;
uart_rxd_d1<=1'b0;
end
else begin
uart_rxd_d0<=uart_rxd;
uart_rxd_d1<=uart_rxd_d0;
end
end
(3)计数。
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
clk_cnt<=9'b0;
else if(rx_flag)begin
if(clk_cnt<BPS_cnt-1)
clk_cnt<=clk_cnt+1'b1;
else
clk_cnt<=9'b0;
end
else
clk_cnt<=9'b0;
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rx_cnt<=4'd0;
else if(rx_flag)begin
if(clk_cnt==BPS_cnt-1)
rx_cnt<=rx_cnt+1'b1;
else
rx_cnt<=rx_cnt;
end
else
rx_cnt<=4'd0;
end
(4)串转并。
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rx_data<=8'd0;
else if(rx_flag)
if(clk_cnt==BPS_cnt/2)begin
case(rx_cnt)
4'd1:rx_data[0]<=uart_rxd_d1;
4'd2:rx_data[1]<=uart_rxd_d1;
4'd3:rx_data[2]<=uart_rxd_d1;
4'd4:rx_data[3]<=uart_rxd_d1;
4'd5:rx_data[4]<=uart_rxd_d1;
4'd6:rx_data[5]<=uart_rxd_d1;
4'd7:rx_data[6]<=uart_rxd_d1;
4'd8:rx_data[7]<=uart_rxd_d1;
default:;
endcase
end
else
rx_data<=rx_data;
else
rx_data<=8'd0;
end
uart_rxd使用延迟两个时钟的d1,更稳定,防止亚稳态。
(5)并转串。文章来源:https://www.toymoban.com/news/detail-436708.html
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
uart_txd<=1'b1;
else if(tx_flag)
case(tx_cnt)
4'd0:uart_txd<=1'b0;
4'd1:uart_txd<=tx_data[0];
4'd2:uart_txd<=tx_data[1];
4'd3:uart_txd<=tx_data[2];
4'd4:uart_txd<=tx_data[3];
4'd5:uart_txd<=tx_data[4];
4'd6:uart_txd<=tx_data[5];
4'd7:uart_txd<=tx_data[6];
4'd8:uart_txd<=tx_data[7];
4'd9:uart_txd<=1'b1;
default:;
endcase
else
uart_txd<=1'b1;
end
(6)loop。文章来源地址https://www.toymoban.com/news/detail-436708.html
`timescale 1ns / 1ps
module uart_loop(
input sys_clk,
input sys_rst_n,
input recv_done,
input [7:0] recv_data,
input tx_busy,
output reg send_en,
output reg[7:0] send_data
);
reg recv_done_d0;
reg recv_done_d1;
reg tx_ready;
wire recv_done_flag;
assign en_flag= recv_done_d0& ~recv_done_d1;
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
recv_done_d0<=1'b0;
recv_done_d1<=1'b0;
end
else begin
recv_done_d0<=recv_done;
recv_done_d1<=recv_done_d0;
end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
send_en<=1'b0;
send_data<=8'd0;
tx_ready<=1'b0;
end
else begin
if(recv_done_flag)begin
tx_ready<=1'b1;
send_en<=1'b0;
send_data<=recv_data;
end
else if((~tx_busy)&&tx_ready)begin
tx_ready<=1'b0;
send_en<=1'b1;
end
end
end
endmodule
到了这里,关于Verilog(1)UART串口通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!