Verilog(1)UART串口通信

第一部分为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)并转串。

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。

`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

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值