首页 > 其他分享 >小梅哥课程学习——串口发送应用之发送数据(可在vivado中仿真出现正确波形)

小梅哥课程学习——串口发送应用之发送数据(可在vivado中仿真出现正确波形)

时间:2023-03-03 11:34:27浏览次数:47  
标签:tx send vivado bps 串口 发送数据 input DR 50000000

//1、底层代码源代码发送10位数据
module uart_pr(
    clk,
    reset_n,
    send_go,
    data,
    baud_set,
    tx_done,
    uart_tx
    );
    input clk;
    input reset_n;
    input send_go;
    input [7:0]data;
    input [2:0]baud_set;
    output reg tx_done;
    output reg uart_tx;
    
    
    //再书写关于bps_DR的选择计算
    reg [17:0] bps_DR;
    always@(*)
        case(baud_set)
            0:bps_DR=50000000/9600;
            1:bps_DR=50000000/19200;
            2:bps_DR=50000000/38400;
            3:bps_DR=50000000/57600;
            4:bps_DR=50000000/115200;
            default:bps_DR=50000000/9600;
        endcase
    reg send_en;
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        send_en<=0;
    else if(send_go)//记住这边只能用顶层的计数counter,不能用底层的div_cnt以及bps_cnt;
        send_en<=1;
    else if(tx_done)
        send_en<=0;
        
    //存储数据
    reg [7:0]r_data;
    always@(posedge clk or negedge reset_n)//这里为什么不需要复位的下降沿
    if(!reset_n)
        r_data<=0;
    else if(send_go)
        r_data<=data;
    else
        r_data<=r_data;
    //首先书写对应波特率的计数,分频div_cnt
    //根据最低的波特率来确定div_cnt的宽度
    reg [17:0]div_cnt;
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        div_cnt<=0;
    else if(send_en)begin
        if(div_cnt==bps_DR-1)
            div_cnt<=0;
        else
            div_cnt<=div_cnt+1'b1;
    end
    else
        div_cnt<=0;
        
    wire bps_clk;
    assign bps_clk=(div_cnt==1);
    //开始书写下一个计数bps_cnt,来实现10为数据的发送
    reg [3:0] bps_cnt;
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        bps_cnt<=0;
    else if(send_en)begin
        if(bps_clk)begin
            if(bps_cnt==11)
                bps_cnt<=0;
            else
                bps_cnt<=bps_cnt+1'b1;
        end
    end
    else
        bps_cnt=0;
    //开始书写发送10位的数据
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        uart_tx<=1;
    else case(bps_cnt)
        1:uart_tx<=0;
        2:uart_tx<=r_data[0];
        3:uart_tx<=r_data[1];
        4:uart_tx<=r_data[2];
        5:uart_tx<=r_data[3];
        6:uart_tx<=r_data[4];
        7:uart_tx<=r_data[5];
        8:uart_tx<=r_data[6];
        9:uart_tx<=r_data[7];
        10:uart_tx<=1;
        11:uart_tx<=1;
        default:uart_tx<=1;
    endcase

    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        tx_done<=0;
    else if((bps_cnt==10)&&(bps_clk==1))
        tx_done<=1;
    else
        tx_done<=0;
endmodule
//2、底层代码仿真文件
`timescale 1ns / 1ps
module uart_pr_tb();
    reg clk;
    reg reset_n;
    reg send_en;
    reg [7:0]data;
    reg [2:0]baud_set;
    wire tx_done;
    wire uart_tx;
    uart_pr uart_pr_tb(
        .clk(clk),
        .reset_n(reset_n),
        .send_en(send_en),
        .data(data),
        .baud_set(baud_set),
        .tx_done(tx_done),
        .uart_tx(uart_tx)
        );
    initial clk=1;
    always#10 clk=!clk;
    
    initial begin
        reset_n=0;
        data=0;
        send_en=0;
        baud_set=4;
        #201;
        reset_n=1;
        #20;
        data=8'h57;
        send_en=1;
        @(posedge tx_done)
            send_en=0;
            #2000;
            data=8'h75;
            send_en=1;
        @(posedge tx_done)
            send_en=0;
            #20000;
            $stop;
    end
        

endmodule
3、顶层代码源文件
//每10ms以115200的波特率发送一个数据,每次发送的
//数据比前一个数据大一(计数器)
//顶层设计模块
module uart_test1(
    clk,
    reset_n,
    uart_tx
    );
    input clk;
    input reset_n;
    output uart_tx;
    
    reg send_go;//这是顶层的send_en放在下面会出错
    reg [7:0] data;
    //先将发送10位数据的uart进行例化
    uart_pr uart_pr_inst0(
        .clk(clk),
        .reset_n(reset_n),
        .send_go(send_go),
        .data(data),
        .baud_set(3'd4),
        .tx_done(tx_done),
        .uart_tx(uart_tx)
    );
    //先写出一个10ms的计数器
    reg [18:0]counter;
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        counter<=0;
    else if(counter==499999)
        counter<=0;
    else
        counter<=counter+1'b1;
    //书写发送信号send_en
    //底层不是控制过send_en了吗??怎么这里还写控制send_en
    //因为底层控制send_en在testbench中控制的,最后不会在板级验证的时候起作用
    //那只在testbench中也就是仿真波形中会出现。
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        send_go<=0;
    else if(counter==1)//记住这边只能用顶层的计数counter,不能用底层的div_cnt以及bps_cnt;
        send_go<=1;
    else    //设置send_go的时候一定要注意,什么时候开始,什么时候结束要形成闭环。
        send_go<=0;//else还是要加,只不过不用带tx_done因为tx_done已经在顶层模块说明过了
    //书写data的每次加1;
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        data<=0;
    else if(tx_done)
        data<=data+1'b1;
endmodule
4、顶层代码仿真文件
`timescale 1ns / 1ps
module uart_test1_tb();
    reg clk;
    reg reset_n;
    wire uart_tx;
    uart_test1 uart_test1_inst0(
    .clk(clk),
    .reset_n(reset_n),
    .uart_tx(uart_tx)
    );
    
    initial clk=1;
    always #10 clk=!clk;
    
    initial begin
    reset_n=0;
    #201;
    reset_n=1;
    
    #50000000;
    $stop;
    
    end 
endmodule

 

标签:tx,send,vivado,bps,串口,发送数据,input,DR,50000000
From: https://www.cnblogs.com/wangwin4/p/17174943.html

相关文章