Verilog(2)-简单的串口通信设计

Date是8位并行的传输数据,通过输出端口uart_tx串行输出。

Baud_set代表波特率的种类代号(0,1,2,3,4···)。

send_en表示发送数据指令,高电平时发送数据。

Tx_Done表示一个Date数据发送结束时的反馈,高电平代表发送数据完成。

 uart_tx传输信号形式:起始位低电平,终止位高电平,中间8位传输数据。

下面展示代码

module uart_byte_tx(
    clk,
    rst_n,
    Date,
    send_en,
    Baud_set,
    uart_tx,
    Tx_Done
    );
    
    input clk,rst_n;
    input [7:0]Date;
    input send_en;
    input [2:0]Baud_set;
    output reg uart_tx;
    output reg Tx_Done;
    
    
//对波特率进行分配,便于计数
    reg [17:0]byte_DR;
    always@(*)begin
        case(Baud_set)
            0: byte_DR = 1_000_000_000/9600/20;
            1: byte_DR = 1_000_000_000/19200/20;
            2: byte_DR = 1_000_000_000/38400/20;
            3: byte_DR = 1_000_000_000/57600/20;
            4: byte_DR = 1_000_000_000/115200/20;
            default: byte_DR = 1_000_000_000/115200/20;
        endcase
    end
    
  
//计数一个数据位  
   reg [17:0]cnt0;
//   wire   end_cnt0; 
        always @(posedge clk or negedge rst_n)
       if(!rst_n)begin
                cnt0 <= 0;
            end
            else if(send_en)begin
                if(cnt0 == byte_DR - 1)
                    cnt0 <= 0;
                else
                    cnt0 <= cnt0 + 1;
            end
        else
            cnt0 = 0;

//        assign send_en = 1;       
//        assign end_cnt0 = send_en && cnt0 == byte_DR - 1;   


//计数8个传输位和2个起始终止位,共计10位
        reg [3:0]cnt1;
        always @(posedge clk or negedge rst_n)
            if(!rst_n)begin
                cnt1 <= 0;
            end
            else if(send_en)begin
                if(cnt0 == 1)begin 
/*
if(cnt0 == byte_DR - 1)这里据说是uart延时一个数据位发送了,不懂啊,但是cnt1后面出现了11。ps:解决了是因为测试文件写错了。没有在@(posedge Tx_Done)后面加上send_en=0;
/*
                    if(cnt1 == 11)
                        cnt1 <= 0;  
                    else 
                        cnt1 <= cnt1 + 1;   
                 end
            end
            else
                cnt1 <= 0;

 //       assign add_cnt1 = end_cnt0;       
 //       assign end_cnt1 = send_en && cnt1== 11 - 1;   


//赋值10个数据位
    always  @(posedge clk or negedge rst_n)begin
       if(!rst_n)begin
                uart_tx <= 1;
                Tx_Done <= 0;
            end
        else  begin
        case(cnt1) 
            0: Tx_Done <= 0;
            1: uart_tx <= 0;
            2: uart_tx <= Date[0];
            3: uart_tx <= Date[1];
            4: uart_tx <= Date[2];
            5: uart_tx <= Date[3];
            6: uart_tx <= Date[4];
            7: uart_tx <= Date[5];
            8: uart_tx <= Date[6];
            9: uart_tx <= Date[7];
            10: uart_tx <= 1'b1; 
            11:begin uart_tx <= 1;Tx_Done <= 1; end
            default:uart_tx <= 1;
        endcase
        end
    end
endmodule

测试代码tb

`timescale 1ns / 1ns

module uart_byte_tx_tb(

    );
 
    reg clk,rst_n;
    reg [7:0]Date;
    reg send_en;
    reg [2:0]Baud_set;
    wire uart_tx;
    wire Tx_Done;

uart_byte_tx inst1(
  .clk(clk),
  .rst_n(rst_n),
  .Date(Date),
  .send_en(send_en),
  .Baud_set(Baud_set),
  .uart_tx(uart_tx),
  .Tx_Done(Tx_Done)
    );


    initial clk = 1;
    always #10 clk = ~clk;
    
    initial begin
            rst_n = 0;
            send_en = 0;
            Date = 0;
            Baud_set = 4;
            #201;
            rst_n = 1;
            #100;
            send_en = 1;
            Date = 8'b1001_0110;
            #20;
            @(posedge Tx_Done);
            send_en = 0;
            #20000;
            send_en = 1;
            Date = 8'b0110_1001;
            #20;
            @(posedge Tx_Done);
            send_en = 0;
            #20000;
            $stop;
        end

endmodule

仿真结果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值