Verilog学习笔记八(串口数据接收与发送)

一、串口协议简介

二、串口数据接收

 波特率:波特率表示每秒钟传送的码元符号的个数,它是对符号传输速率的一种度量

 

 等空闲状态只需一次(保证有10bit以上的连续的1):

 verilog代码:

//2023/3/30 lzp
//串口接收
`timescale 1ns/10ps
module Serial_rev(
                clk,
                res,
                RX,
                data_out,
                en_data_out
                );
input           clk;
input           res;
input           RX;
output[7:0]     data_out; //接收字节输出
output          en_data_out; //输出使能

reg[7:0]        state; //主状态机
reg[12:0]       count; //计数器,计算bit宽度,24Mhz/4800=5000
reg[3:0]        count_bit; //用于计算bit数

reg             RX_delay; //RX的延时
reg             en_data_out;
reg[7:0]        data_out;

always@(posedge clk or negedge res) 
if(!res) begin
    state<=0;
    count<=0;
    count_bit<=0;
    RX_delay<=0;
    en_data_out<=0;
end
else begin
    RX_delay<=RX;
    case(state)
        0://等空闲
        begin
            //5000次转一轮
            if(count == 5000-1) begin
                count<=0;
            end
            else begin
                count<=count+1;
            end
            
            if(count == 0) begin
                if(RX == 1) begin
                    count_bit<=count_bit+1;
                end
                else begin
                    count_bit<=0;
                end
            end
            
            //到12表示到达了空闲状态
            if(count_bit == 12) begin
                state<=1;
            end
            
        end
        1://等起始位
        begin
            en_data_out<=0;
            if(~RX&RX_delay) begin
                state<=2;
            end
        end
        2://收最低位b0
        begin
            if(count == 7500-1) begin
                count<=0;
                data_out[0]<=RX;
                state<=3;
            end
            else begin
                count<=count+1;
            end
        end
        3://收最低位b1
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[1]<=RX;
                state<=4;
            end
            else begin
                count<=count+1;
            end
        end
        4://收最低位b2
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[2]<=RX;
                state<=5;
            end
            else begin
                count<=count+1;
            end
        end
        5://收最低位b3
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[3]<=RX;
                state<=6;
            end
            else begin
                count<=count+1;
            end
        end
        6://收最低位b4
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[4]<=RX;
                state<=7;
            end
            else begin
                count<=count+1;
            end
        end
        7://收最低位b5
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[5]<=RX;
                state<=8;
            end
            else begin
                count<=count+1;
            end
        end
        8://收最低位b6
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[6]<=RX;
                state<=9;
            end
            else begin
                count<=count+1;
            end
        end
        9://收最低位b7
        begin
            if(count == 5000-1) begin
                count<=0;
                data_out[7]<=RX;
                state<=10;
            end
            else begin
                count<=count+1;
            end
        end
        10://产生使能脉冲
        begin
            en_data_out<=1;
            state<=1;
        end
        default:
        begin
            state<=0;
            count<=0;
            count_bit<=0;
            en_data_out<=0;
        end
    endcase
end

endmodule

//testbench
module serial_rev_tb;
reg             clk;
reg             res;
wire            RX;
wire[7:0]       data_out;
wire            en_data_out;
      
reg[25:0]       RX_send; //装有串口字节数据
reg[12:0]       con;
      
      
Serial_rev Serial_rev(//同名例化
                clk,
                res,
                RX,
                data_out,
                en_data_out
                );
assign          RX=RX_send[0]; //连接RX  
       
initial begin
            clk<=0;res<=0;RX_send<={1'b1,8'h0a,1'b0,16'hffff};con<=0;
    #17     res<=1;
    #1000   $stop;
end

always#(5) clk=~clk;

always@(posedge clk) begin
    if(con == 5000-1) begin
        con<=0;
    end
    else begin
        con<=con+1;
    end
    
    if(con == 0) begin
        //循环右移
        RX_send[24:0]<=RX_send[25:1];
        RX_send[25]<=RX_send[0];
    end
end
endmodule

三、串口数据发送

verilog代码:

//2023/3/30 lzp
//串口发送
`timescale 1ns/10ps
module Serial_send(
                clk,
                res,
                data_in,
                en_data_in,
                TX,
                rdy
                );
input           clk;
input           res;
input[7:0]      data_in;//准备发送的数据
input           en_data_in;//发送使能
output          TX;//输出数据
output          rdy;//空闲标志,0表示空闲

reg[3:0]        state;//状态标志
reg[9:0]        send_buf;//发送缓存
reg[12:0]       con;//用于计算波特周期
reg[9:0]        send_flag;//用于判断右移结束

reg             rdy;//0表示空闲

assign          TX=send_buf[0];//连接TX到发送缓存最低位

always@(posedge clk or negedge res)
if(!res) begin
    state<=0;
    rdy<=0;
    send_buf<=1; //因为TX空闲为1,所以sendbuf初始最低位为1
    con<=0;
    send_flag<=10'b10_0000_0000;
end
else begin
    case(state)
        0://等待发送使能
        begin
            if(en_data_in == 1) begin
                state<=1;
            end
        end
        1://填充发送寄存器
        begin
            send_buf<={1'b1,data_in,1'b0};
            send_flag<=10'b10_0000_0000;
            rdy<=1;
            state<=2;
        end
        2://发送寄存器右移
        begin
            if(con == 5000-1) begin
                con<=0;
            end
            else begin
                con<=con+1;
            end
            
            if(con == 5000-1) begin
                send_buf[8:0]<=send_buf[9:1];
                send_flag[8:0]<=send_flag[9:1];
            end
            
            //发送完毕
            if(send_flag[0] == 1) begin
                rdy<=0;
                state<=0;
            end
        end
    endcase
end

endmodule

//testbench
module serial_send_tb;

reg             clk;
reg             res;
reg[7:0]        data_in;
reg             en_data_in;
wire            TX;
wire            rdy;

Serial_send Serial_send(
                clk,
                res,
                data_in,
                en_data_in,
                TX,
                rdy
                );

initial begin
            clk<=0;
            res<=0;
            data_in<=0;
            en_data_in<=0;
            data_in<=8'b1100_1100;
    #17     res<=1;
    #30     en_data_in<=1;
    #10     en_data_in<=0;
    #1000   $stop;
end

always#(5) clk=~clk;

endmodule

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值