我是靠谱客的博主 结实奇迹,最近开发中收集的这篇文章主要介绍【verilog】UART串口发送(FPGA)简述核心代码仿真测试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  • 简述
  • 核心代码
  • 仿真测试

简述

串口发送是以一定速率发送单bit数据,通常一组数据为10bit。空闲状态为高电平,起始位为0,中间以低位在前的方式发送8bit数据,终止位为1。
采用计数器 [cnt_baud] 对系统时钟进行计数,计满值即为预设的波特率值 [baud_num]
在这个计数过程中,每当计数值为1时,就产生一个标志值 [flag1]
采用计数器 [cnt_for_flag1] 对flag1进行计数11次,当计数值达到11时,同步清零。
所以cnt_for_flag1 = 11 只能维持1个系统时钟,并不能维持一个baud_num。
能维持一个baud_num的为计数值1~10。利用cnt_for_flag1作为多路器的选择端分别发送出10个bit的数据。
当cnt_for_flag1值为11时,代表一次发送完成,产生done信号。

核心代码

module ser_tx(data,en,clk,rst,tx,done);
    input [7:0] data;
    input en;
    input clk;
    input rst;

    output reg tx;
    output reg done;

    reg [15:0] baud_num = 16'd5207; //5207=9600、2603=19200、1301=38400、867=57600、433=115200

    /*将引脚 <input [7:0] data> 进行一级寄存 -> reg_data*/
    reg [7:0]reg_data;   
    always@(posedge clk or negedge rst) begin
        if(!rst)
            reg_data <= 8'b0;
        else if(en)begin 
            reg_data <= data;     
        end                  
        else
            reg_data <= data;
    end

    /*计数器:0~5207~0~5207....*/
    reg [15:0]cnt_baud;
    always@(posedge clk or negedge rst)
    begin
        if(!rst)
            cnt_baud <= 1'b0;
        else if(cnt_baud == baud_num)
            cnt_baud <= 1'b0;
        else
            cnt_baud <= cnt_baud + 1'b1;          
    end

    /*0~5207这个过程中,每当计数到1的时候就产生一个flag*/
    reg flag1;
    always@(posedge clk or negedge rst)
    begin
        if(!rst)
            flag1 <= 1'b0;
        else if(cnt_baud == 16'd1)
            flag1 <= 1'b1;
        else
            flag1 <= 1'b0;         
    end

    /*对flag1进行计数,计数11次,但11只能维持1个clk,并不能维持9600bps,然后就被清0*/
    reg [3:0] cnt_for_flag1;
    always@(posedge clk or negedge rst)
    begin
        if(!rst)
            cnt_for_flag1 <= 1'b0;
        else if(cnt_for_flag1 == 4'd11)
            cnt_for_flag1 <= 1'b0;    
        else if(flag1 == 1'd1)
            cnt_for_flag1 <= cnt_for_flag1 + 1'b1;
        else
            cnt_for_flag1 <= cnt_for_flag1;
    end


    /*依次发送起始位、数据位、终止位*/
    always@(posedge clk or negedge rst)
    begin
        if(!rst)
        tx <= 1'd1; //根据时序图,tx的闲时状态是高电平。
        else
            begin
                case (cnt_for_flag1)
                    4'd0: tx <= 1'd1;  //空闲状态
                
                    4'd1: tx <= 1'd0;  //起始位
                
                    4'd2: tx <= reg_data[0]; //低位在前
                    4'd3: tx <= reg_data[1]; 
                    4'd4: tx <= reg_data[2];    
                    4'd5: tx <= reg_data[3]; 
                    4'd6: tx <= reg_data[4]; 
                    4'd7: tx <= reg_data[5]; 
                    4'd8: tx <= reg_data[6]; 
                    4'd9: tx <= reg_data[7]; 

                    4'd10: tx <= 1'd1; //终止位
                    default:tx <= 1'd1;//空闲状态
                endcase               
            end
     end

    //每次计数器“cnt_for_flag1”值为11时,代表一次发送完成,产生done信号。
    always@(posedge clk or negedge rst) begin
        if(!rst)
            done <= 1'd0;
        else if(cnt_for_flag1 == 4'd11) //cnt_to_10计数到11自动清零
            done <= 1'd1;                 
        else
            done <= 1'd0;
    end

endmodule

仿真测试

发送8bit的 data1 = 8’b01001101 作为测试!

`timescale 1ns/1ns
module ser_tx_tb;

    reg [7:0] data1;
    reg en1;
    reg clk1;
    reg rst1;

    wire  tx1;
    wire  done1;

    
    ser_tx txer
                (
                .data(data1),
                .en(en1),
                .clk(clk1),
                .rst(rst1),
                .tx(tx1),
                .done(done1)
                );

    initial clk1 = 1'b1;
    always#10 clk1 = ~clk1;

    initial begin
    rst1 = 1'b0;    //未运行状态

    #400;
    rst1 = 1'b1;

    data1 = 8'b01001101;

    en1 = 1;
    #20;//一个时钟周期
    en1 = 0;

    #4000000;

     $stop;

    end
endmodule

在这里插入图片描述

在这里插入图片描述

最后

以上就是结实奇迹为你收集整理的【verilog】UART串口发送(FPGA)简述核心代码仿真测试的全部内容,希望文章能够帮你解决【verilog】UART串口发送(FPGA)简述核心代码仿真测试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部