首页 > 其他分享 >小梅哥课程学习——串口发送应用之发送数据

小梅哥课程学习——串口发送应用之发送数据

时间:2023-03-02 22:23:16浏览次数:48  
标签:tx uart bps 串口 发送数据 input DR 小梅哥 50000000

//此代码的注意事项,首先这个代码不能仿真成功会出现一定的时间延迟,
//因为在做板级验证的时候把时间改成了100ms发送一次,要想仿真成功,把时间改成499999
//使用上一节课设计的发送模块,设计一个数据发送器,
//每10ms以115200的波特率发送一个数据,每次发送的
//数据比前一个数据大一(计数器)
//首先是发送八位数据的uart_byte_tx的更改的源代码

//1、这里我使用的是(uart_p==uart_byte_tx)
//这两个是底层模块

module uart_p(
    clk,
    reset_n,
    send_go,
    data,
    baud_set,
    uart_tx,
    tx_done
    );
    input clk;
    input reset_n;
    input send_go;
    input [7:0] data;
    input [2:0]baud_set;
    output reg uart_tx;
    output reg tx_done;
    //书写不同波特率对应的模式
    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)
        send_en<=1;
    else if(tx_done)
        send_en<=0;
        
        
    //书写关于data的寄存问题
    reg [7:0] r_data;
    always@(posedge clk)
    if(send_go)
        r_data<=data;
    else
        r_data<=r_data;
    
    //先写一个适合波特率的定时
    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);//放在上面就不行,还跟位置有关系。
    //将时间拼接为11个时间段
    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;
    //这里一定要注意不加else bps_cnt<=0;因为条件是div_cnt==bps_DR-1,如果else就会出现bps_cnt一直为0的怪情况。
    
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        uart_tx<=1'b1;
    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_clk==1)&&(bps_cnt==10))
        tx_done<=1;
    else
        tx_done<=0;
endmodule

//2、uart_byte_tx_tb仿真代码(这里我使用的是uart_p_tb==uart_byte_tx_tb)

`timescale 1ns / 1ns
module uart_p_tb();
    reg clk;
    reg reset_n;
    reg send_en;
    reg [7:0] data;
    reg [2:0]baud_set;
    wire uart_tx;
    wire tx_done;
    uart_p uart_p_inst0(
    .clk(clk),
    .reset_n(reset_n),
    .send_en(send_en),
    .data(data),
    .baud_set(baud_set),
    .uart_tx(uart_tx),
    .tx_done(tx_done)
);
    initial clk=1;
    always #10 clk=~clk;
    
    initial begin 
        reset_n=0;
        send_en=0;
        data=0;
        baud_set=4;
        #201;
        reset_n=1;
        #20;
        
        send_en=1;
        data=8'h57;
       
        @(posedge tx_done)
        send_en=0;
        #2000;
        send_en=1;
        data=8'h75;
        #20;
        @(posedge tx_done)
        send_en=0;
        #200000;
        $stop;
    end
endmodule

//3、uart_test仿真代码,这里面是顶层模块

module uart_test(
    clk,
    reset_n,
    uart_tx
    );
    input clk;
    input reset_n;
    output uart_tx;
    
    reg [26:0] counter;
    reg send_go;
    reg [7:0]data;
    //先进行底层模块的例化
    //例化只用写对应的端口和连接
    uart_p uart_p_inst0(
        .clk(clk),
        .reset_n(reset_n),
        .send_go(send_go),
        .baud_set(3'd4),
        .data(data),
        .uart_tx(uart_tx),
        .tx_done(tx_done)
    );
    //先书写10ms的定时器
    
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        counter<=0;
    else if(counter==4999999)
        counter<=0;
    else
        counter<=counter+1;
    //开始书写发送信号send_en
    
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        send_go<=0;
    else if(counter==1)
        send_go<=1;
    else
        send_go<=0;
    //为什么不管tx_done??????
        
    //开始书写发送的数据,让其执行每次加一的操作。
    
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        data<=0;
    else if(tx_done)
        data<=data+1'b1;
endmodule

//4、uart_test_tb仿真代码,这里面是顶层模块

`timescale 1ns / 1ps
module uart_test_tb();
    reg clk;
    reg reset_n;
    wire uart_tx;
    uart_test uart_test_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,uart,bps,串口,发送数据,input,DR,小梅哥,50000000
From: https://www.cnblogs.com/wangwin4/p/17173771.html

相关文章