首页 > 其他分享 >串口接收模块——verilog实现

串口接收模块——verilog实现

时间:2022-12-17 01:11:33浏览次数:47  
标签:Name CLK uart rx verilog 模块 串口 byte reg

1、设计想法

原理与之前的串口发送模块一样,1位的数据位和8位的数据位再加上1位的停止位。唯一不同的是在接收的时候要考虑到有干扰的情况下,为了避免干扰,我们对每位数据进行多次采样,按出现概率大的值为该数据位的值。
image
如果按照通常想法在每bits位中间取值的话,bit3位出现图中的干扰很有可能会读出错误的值。所以需要对每位进行多次抽样进行判断。
image

每位要抽8次的话,那需要将每个波特段分成9等分。

2、状态机设定

image

3、模块代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Lclone
// 
// Create Date: 2022/12/16 15:37:44
// Design Name: uart_byte_rx
// Module Name: uart_byte_rx
// Project Name: uart_byte_rx
// Target Devices: 
// Tool Versions: 
// Description: 8位串口发送模块
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_byte_rx
  # (
        parameter   RX_BAUD  = 9600,				//波特率
        parameter   CLK_FQC  = 50_000_000,			//模块时钟频率
        parameter   BAUD_CNT = CLK_FQC/RX_BAUD)			//模块每波特需要计数的次数(设置此端口方便仿真用)
    (
        input               Clk,				//时钟频率接口
        input               Rst_n,				//复位接口
        input               Uart_rx,				//串口接收接口
        output  reg  [7:0]  Data				//接收到的数据接口
    );
    
    reg            uart_rx_r;					//延一拍
    reg            uart_rx_rr;					//延两拍
    reg            receiv_begin;				//接收开始信号
    reg            receiv_flag;					//接收状态信号
    reg   [ 3:0]   state;					//状态机寄存器
    reg   [15:0]   baud_cnt;					//波及计数器
    reg   [ 3:0]   sampel_cnt;					//采样计数器
    reg            sampel_en;					//采样使能
    reg            sampel_ref;					//样本寄存器
    reg   [ 3:0]   acc;						//累加寄存器
    reg   [ 3:0]   bit_cnt;					//数据位寄存器
    
    always @(posedge Clk) begin   //下降沿捕获
        uart_rx_r <= Uart_rx;
        uart_rx_rr <= uart_rx_r;
    end
    
    always @(posedge Clk or negedge Rst_n) begin	//接收信号发生
        if(Rst_n == 0)
            receiv_begin <= 0;
        else if(state == 0 & uart_rx_rr & ~uart_rx_r)
            receiv_begin <= 1'b1;
        else
            receiv_begin <= 0;            
    end
    
    always @(posedge Clk or negedge Rst_n) begin	//状态机
        if(Rst_n == 0) begin
            state <= 0;
            sampel_ref <= 8'b0;
            acc <= 8'b0;
            Data <= 8'b0;
        end
        else case(state)
            0: 		//空闲状态
                if(receiv_begin == 1)
                    state <= 3'd1;
                else
                    state <= 0;
            
            1: begin	//抽样状态
                    if(sampel_en == 1) begin
                           sampel_ref <= Uart_rx;
                           state <= 3'd2;
                    end

                    else
                        state <= 3'b1;
               end   
                    
            2: begin	//数据判断状态

                    acc <= acc + sampel_ref;
                   
                    if(sampel_cnt == 7) begin
                        if(acc >= 4)
                            begin Data[7] <= 1'b1; state <= 3'd3;acc <= 8'b0; end
                        else
                            begin Data[7] <= 0; state <= 3'd3;acc <= 8'b0; end
                    end
                    
                    else
                        state <= 3'd1;
               end                            

            3: begin	//数据移位状态
                    if(bit_cnt < 8) begin
                        Data <= Data >> 1;
                        state <= 3'd1; 
                    end
                    
                    else 
                        state <= 0;
            end
            
            default:;
       endcase
    end
    
    always @(posedge Clk or negedge Rst_n) begin	//接收进行标志
        if(Rst_n == 0)
            receiv_flag <= 0;
        else if(receiv_begin == 1)
            receiv_flag <= 1'b1;
        else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)
            receiv_flag <= 1'b0;
    end
    
    always @(posedge Clk or negedge Rst_n) begin	//波特计数
        if(Rst_n == 0)     
            baud_cnt <= 0;
        else if(receiv_flag == 1) begin
            if(baud_cnt == BAUD_CNT - 1)
                baud_cnt <= 0;
            else
                baud_cnt <= baud_cnt + 1'b1;
            end
        else
            baud_cnt <= 0;      
    end
    
    always @(posedge Clk or negedge Rst_n) begin	//采样计数
        if(Rst_n == 0) begin
            sampel_cnt <= 0;
            sampel_en <= 0;
        end
        else if(receiv_flag == 1) begin
            case(baud_cnt)
                BAUD_CNT/9*1-1 : begin sampel_cnt <= 0; sampel_en <=1; end
                BAUD_CNT/9*2-1 : begin sampel_cnt <= 1; sampel_en <=1; end
                BAUD_CNT/9*3-1 : begin sampel_cnt <= 2; sampel_en <=1; end
                BAUD_CNT/9*4-1 : begin sampel_cnt <= 3; sampel_en <=1; end
                BAUD_CNT/9*5-1 : begin sampel_cnt <= 4; sampel_en <=1; end
                BAUD_CNT/9*6-1 : begin sampel_cnt <= 5; sampel_en <=1; end
                BAUD_CNT/9*7-1 : begin sampel_cnt <= 6; sampel_en <=1; end
                BAUD_CNT/9*8-1 : begin sampel_cnt <= 7; sampel_en <=1; end
                BAUD_CNT/9*9-1 : sampel_cnt <= 0;
                default:sampel_en <=0;
            endcase
        end
    end
    
    always @(posedge Clk or negedge Rst_n) begin	//数据位计数
        if(Rst_n == 0)
            bit_cnt <= 0;
        else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)
            bit_cnt <= 0;
        else if(baud_cnt == BAUD_CNT - 1)
            bit_cnt <= bit_cnt + 1'b1;
    end
endmodule

4、仿真验证

(1)仿真激励文件

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/12/16 21:36:04
// Design Name: 
// Module Name: uart_byte_rx_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module uart_byte_rx_tb();
    
    reg        CLK_50M;
    reg        RST_N;
    wire [7:0] Data;    
    reg        Uart_rx;
    reg  [7:0] test_data;
    uart_byte_rx 
  # (
        .RX_BAUD   (9600),
        .CLK_FQC   (50_000_000),
        .BAUD_CNT  (50))
    uart_byte_rx_inst
    (
        .Clk        (CLK_50M),
        .Rst_n      (RST_N),
        .Uart_rx    (Uart_rx),
        .Data       (Data)
    );
    
    
    always #10 CLK_50M  <= ~CLK_50M;
    
    initial begin
    CLK_50M <= 1'b0;
    RST_N   <= 1'b0;
    Uart_rx <= 1'b1;
    test_data <= 8'h0;
    #100
    RST_N   <= 1'b1;
    #20
        test_data <= 8'haf;
        #1000
        Uart_rx <= 1'b0;
        #1000             
        Uart_rx <= test_data[0];
        #1000             
        Uart_rx <= test_data[1];
        #1000             
        Uart_rx <= test_data[2];
        #1000             
        Uart_rx <= test_data[3];
        #1000             
        Uart_rx <= test_data[4];
        #1000             
        Uart_rx <= test_data[5];
        #1000             
        Uart_rx <= test_data[6];
        #1000             
        Uart_rx <= test_data[7];
        #1000             
        Uart_rx <= 1'b1;
     #1000
        test_data <= 8'h56;
        #1000
        Uart_rx <= 1'b0;
        #1000             
        Uart_rx <= test_data[0];
        #1000             
        Uart_rx <= test_data[1];
        #1000             
        Uart_rx <= test_data[2];
        #1000             
        Uart_rx <= test_data[3];
        #1000             
        Uart_rx <= test_data[4];
        #1000             
        Uart_rx <= test_data[5];
        #1000             
        Uart_rx <= test_data[6];
        #1000             
        Uart_rx <= test_data[7];
        #1000             
        Uart_rx <= 1'b1;
    #1000
    $stop;
    end
    
    
endmodule

(2)仿真结果

image

标签:Name,CLK,uart,rx,verilog,模块,串口,byte,reg
From: https://www.cnblogs.com/Lclone/p/16988555.html

相关文章

  • PYTHON 模块 - random
    1.1random模块用于生成随机数。1.2相关方法random.random()用于生成一个0到1的随机浮点数:0<=n<1.0>>>importrandom>>>random.random()0.6067277881757......
  • PYTHON 模块
    1.1模块模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。1.2导入模块import模块1,模块2,...定......
  • Web Serial Debug-浏览器串口调试工具
    WebSerialDebug浏览器串口调试工具仅测试了Edge和Chrome浏览器,其他浏览器未测试是否可用在线体验:https://itldg.github.io/web-serial-debug/国内体验:https......
  • SAP ERP学习笔记 -- 物料管理模块
    物料管理模块蓝图​ 模块简介  物料管理模块(MM)覆盖了一个集成供应链(物料需求计划、采购、库存和库房管理)所有有关物料管理的任务。 1. 采购管理系统2. 库存管理系统3......
  • Verilog 时延与过程结构
    一、关键词:时延,惯性时延连续赋值延时语句中的延时,用于控制任意操作数发生变化到语句左端赋予新值之间的时间延时。时延一般是不可综合的。寄存器的时延也是可以控制的,这部......
  • 如何正确使用工业长距离光模块?
    现如今,随着5G技术的到来,咱们日常生活当中许多关于网络技术的应用也发生了巨大的改变,同理,关于在工业上经常使用的光模块应用随着网络的发展,从短距离到长距离也慢慢的发展成熟......
  • chrome浏览器启用es6语法支持,初次体验浏览器端模块化加载
    注意:最新版本的chrome浏览器已支持module语法,需要在web服务器环境下运行!一、设置浏览器启用es6语法功能注:chrome76版本及以上不再需要设置了,浏览器已默认支持,至于从哪个版......
  • Python 导入模块、文件、包、自定义路径包
    测试环境,假设:主文件绝对路径:/home/ubu/py_test/main.py模块文件:/home/ubu/py_test/con.py模块目录:/home/ubu/py_test/modules/tt.py模块目录:/home/ubu/py_test/modules......
  • 8路编码器脉冲计数器或16路DI高速计数器,Modbus RTU模块 YL69
    特点:●编码器解码转换成标准ModbusRTU协议●可用作编码器计数器或者转速测量●支持8个编码器同时计数,可识别正反转●也可以设置作为16路独立DI高速计数器● 编码器计......
  • GPS开发(2)GPS ROS串口采集-pubx数据解析
      pubx协议数据解析   CMakeLists.txt  cmake_minimum_required(VERSION3.0.2)project(v1_GetGPS)##CompileasC++11,supportedinROSKineti......