FPGA开发——UART回环实现之接收模块的设计

news2024/11/25 4:19:47

一、简介

        因为我们本次进行串口回环的实验的对象是FPGA开发板和PC端,所以在接收和发送模块中先编写接收模块,这样可以在后面更好的进行发送模块的验证。(其实这里先编写哪个模块)都不影响,这里看自己心情,反正都可以独立进行仿真。)

        在上一篇文章中,我们对于UART回环实现的总体系统框架做了一盒简单的构建,所以在实现时我们也按照那个框架来。这里就先对于接收模块进行一个设计。

二、接收模块的基本设计

        本次设计我们采用状态机的实现方式,将状态机划分为四个,第一个就是空闲状态,表示设备没有接收数据,第二个是开始状态,表示设备接收到起始位,第三个接收数据过程状态,用于表示设备接收数据的过程,最后一个就是停止位,表示设备接受数据完成。

三、接收模块的波形图绘制

根据上面的状态机,我们可以据此展开波形图的绘制,分别就是对于信号进行打拍,下降沿检测,两个状态,以及bit和波特率、输出数据等的表示。

        使用三级打拍,利用后两拍信号实现下降沿检测,当检测到下降沿,状态机由IDLE进入到START,然后利用波特率计数器计数1bit的起始位,来到DATA,利用波特率计数器和bit计数器用于接收数据,接收完数据之后进入STOP,最后利用波特率计数器计数1bit的停止位,状态又回到初始的IDLE状态。

 四、代码实现

1、设计文件的编写

        新建一个uart_rx.v文件,如下:在代码编写的过程中我们还需要注意的就是UART在进行通信时是串行通信,二我们的设备中数据时并行的,所以在代码中我们还要实现数据串并型的转换。

//---------<模块及端口声名>-------------------------------------------
module uart_rx( 
    input				clk		 ,
    input				rst_n	 ,
    input				din_rx   ,
    output		[7:0]	dout_data,
    output			    dout_flag	
);								 
//---------<参数定义>------------------------------------------------
parameter CLK_CLY=50_000_000;
parameter BAUD_115200=115200;
parameter BPS_CNT_MAX=CLK_CLY/BAUD_115200; 
parameter     IDLE  =4'b0001,
              START =4'b0010,
              DATA  =4'b0100,
              STOP  =4'b1000;
//---------<内部信号定义>--------------------------------------------
reg           uart_rx_d1;//对异步信号进行同步处理
reg           uart_rx_d2;
reg           uart_rx_d3;

reg     [3:0]  state_c;
reg     [3:0]  state_n;
wire            nedge;//起始位下降沿检测
reg     [8:0]  cnt_bps;//波特率计数器
wire           add_cnt_bps;
wire           end_cnt_bps;

reg     [2:0]  cnt_bit;//bit数据计数器
wire           add_cnt_bit;
wire           end_cnt_bit;

reg     [7:0]  uart_rx_r;//用于存储接收到的数据
reg            rx_flag;//接收数据完成标志位
//第一段:同步时序描述状态转移
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        state_c <=IDLE ;
    end 
    else begin 
        state_c <= state_n;
    end 
end
    
//第二段:组合逻辑判断状态转移条件,描述状态转移规律
always @(*) begin
    case(state_c)
        IDLE  : begin
            if (nedge) 
                state_n=START ;
            else
                state_n=IDLE ;
        end
        START : begin
            if (end_cnt_bps) 
                state_n=DATA ;
            else
                state_n=START ;
        end
        DATA  : begin
            if (end_cnt_bit) 
                state_n=STOP ;
            else
                state_n=DATA ;
        end
        STOP  : begin
            if (end_cnt_bps) 
                state_n=IDLE ;
            else
                state_n=STOP ;
        end
        default : state_n=IDLE ;
    endcase
end
//对uart_rx进行打拍同步处理
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        uart_rx_d1 <= 1'b1;
        uart_rx_d2 <= 1'b1;
        uart_rx_d3 <= 1'b1;
    end  
    else begin 
        uart_rx_d1 <=din_rx;
        uart_rx_d2 <=uart_rx_d1;
        uart_rx_d3 <=uart_rx_d2;
    end 
end
//nedge下降沿检测
assign nedge=~uart_rx_d2 & uart_rx_d3;

//波特率计数器
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_bps <= 9'd0;
    end 
    else if(add_cnt_bps)begin 
        if(end_cnt_bps)begin 
            cnt_bps <= 'd0;
        end
        else begin 
            cnt_bps <= cnt_bps + 1'b1;
        end 
    end
end 

assign add_cnt_bps =(state_c != IDLE) ;
assign end_cnt_bps = add_cnt_bps && (cnt_bps ==(BPS_CNT_MAX-1)) ;

//bit计数器
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_bit <= 9'd0;
    end 
    else if(add_cnt_bit)begin 
        if(end_cnt_bit)begin 
            cnt_bit <= 'd0;
        end
        else begin 
            cnt_bit <= cnt_bit + 1'b1;
        end 
    end
end 

assign add_cnt_bit =(state_c == DATA)&& end_cnt_bps ;
assign end_cnt_bit = add_cnt_bit && (cnt_bit ==(8-1)) ;

//将串行数据变为并行数据
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        uart_rx_r <= 1'b0;
    end 
    else if((state_c==DATA)&&(cnt_bps==BPS_CNT_MAX/2-1))begin 
        uart_rx_r<={uart_rx_d3,uart_rx_r[7:1]};
        //uart_rx_r[cnt_bit]<=uart_rx_d3;
    end 
end

//接收数据完成标志wei
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        rx_flag <= 1'b0;
    end 
    else if(end_cnt_bit)begin 
        rx_flag<= 1'b1;
    end 
    else begin 
        rx_flag<= 1'b0;
    end 
end
assign dout_data = uart_rx_r;
assign dout_flag = rx_flag;
endmodule

2、测试文件的编写

`timescale  1us/1us
module  uart_rx_tb();

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//reg   define
reg             clk          ;
reg             rst_n	     ;
reg             din_rx       ;
wire    [7:0]   dout_data    ;
wire            dout_flag    ;


uart_rx uart_rx_inst(
    /*input            */ .clk	     (clk        ),
    /*input            */ .rst_n     (rst_n	 ),        
    /*input            */ .din_rx    (din_rx     ),
    /*output  reg      */ .dout_data (dout_data  ),
    /*output  reg [7:0]*/ .dout_flag (dout_flag  )
);
parameter CLOCK_CYCLE=20;
//产生时钟
    initial clk = 1'b0;
    always #10 clk = ~clk;

//产生激励
    initial  begin 
        rst_n = 1'b1;
        din_rx = 1;//空闲为高电平
        #(CLOCK_CYCLE*2);
        rst_n = 1'b0;
        #(CLOCK_CYCLE*20);
        rst_n = 1'b1;
        #1002;

        //模拟UART接收模块的串行输入
        //起始位
        din_rx = 0;
        #(434*CLOCK_CYCLE);
        //数据位:8'b1011_0011
        din_rx = 1;//LSB
        #(434*CLOCK_CYCLE);
        din_rx = 1;
        #(434*CLOCK_CYCLE);
        din_rx = 0;
        #(434*CLOCK_CYCLE);
        din_rx = 0;
        #(434*CLOCK_CYCLE);
        din_rx = 1;
        #(434*CLOCK_CYCLE);
        din_rx = 1;
        #(434*CLOCK_CYCLE);
        din_rx = 0;
        #(434*CLOCK_CYCLE);
        din_rx = 1;
        #(434*CLOCK_CYCLE);
        //停止位
        din_rx = 1;
        #(434*CLOCK_CYCLE);

        #(CLOCK_CYCLE*100);
        $stop;
    end

endmodule 

五、波形图仿真

 在波形图中我们观察到dout_data的数据和发送数据不一样,这是因为UART是低位先发,所以在波形图中我们看到的输入和输出数据时相反的,这里需要我们注意一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2045728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大语言模型微调框架Unsloth:简化模型微调流程,提升模型性能

Unsloth 将 Llama-3、Mistral、Phi-3 和 Gemma 等大型语言模型的微调速度提高了 2 倍&#xff0c;内存使用量减少了 70%&#xff0c;而且准确性不会降低&#xff01; 特点 通过手动派生所有计算繁重的数学步骤和手写 GPU 内核&#xff0c;unsloth 可以在不更改任何硬件的情况…

IMU助力跑步参数评估

近期&#xff0c;中国研究团队开发了一种创新的跑步参数评估方法&#xff0c;巧妙结合了IMU和多模态神经网络技术&#xff0c;旨在深入研究并有效评估跑步时的步态参数。 科研团队采用IMU传感器&#xff0c;将其固定在跑者的脚踝处&#xff0c;以实时监测并记录跑步时脚踝的加速…

如何利用RPA自动化流程机器人优化企业财务流程

随着企业规模的扩大和业务的复杂性增加&#xff0c;财务流程管理成了一个关键而复杂的任务。传统的财务流程往往涉及大量的重复性、繁琐的工作&#xff0c;不仅效率低下&#xff0c;而且容易出错。为了解决这些问题&#xff0c;越来越多的企业开始引入RPA机器人流程自动化来优化…

JAVA集中学习第五周学习记录(二)

系列文章目录 第一章 JAVA集中学习第一周学习记录(一) 第二章 JAVA集中学习第一周项目实践 第三章 JAVA集中学习第一周学习记录(二) 第四章 JAVA集中学习第一周课后习题 第五章 JAVA集中学习第二周学习记录(一) 第六章 JAVA集中学习第二周项目实践 第七章 JAVA集中学习第二周学…

打开Office(word、excel、ppt)显示操作系统当前的配置不能运行此应用程序最全解决方案!

我以前用过分区助手把office从c盘挪到d盘了&#xff0c;从那以后office就用不了了&#xff0c;然后我就删了&#xff08;貌似没删干净&#xff09;。 最近由于有使用word的需求&#xff0c;所以我从学校官网找到正版软件的安装包&#xff0c;按照步骤重新卸载电脑中office残留…

基于Java的民宿管理系统

TOC springboot306基于Java的民宿管理系统 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的广泛…

【Mac】Downie 打开提示试用的解决办法?

前情 我们在使用 Downie 的时候&#xff0c;可能遇到提示试用的问题&#xff0c;如下图所示。 原因 旧版本的 Downie 没有卸载干净导致的。 解决办法 先使用 AppCleaner 卸载掉电脑上的 Downie 旧版本软件&#xff0c;必须使用 AppCleaner 卸载。重新安装 Downie 即可。

DNN代码实战

DNN的原理 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&#xff0c;只给它输入特征&#xff0c;它便会可以给出输出特征。神经网络可以分为这么几步&#xff1a;划分数据集、训练网络、测试网络、使用…

C++_2_nullptr关键字(3/3)

本节内容有C的NULL在前面打头阵&#xff0c;学起来犹如探囊取物。 先来分析一段代码&#xff0c;本段代码恰好也结合了上节的宏。 #include<iostream> using namespace std; void f(int x) { cout << "f(int x)" << endl; } void f(int* ptr) { …

Android Settings 跳转流程

我们知道在Settings中&#xff0c;各模块之间的Fragment基本都继承了DashboardFragment&#xff0c;当有点击事件时&#xff0c;就会回调DashboardFragment中的onPerferenceTreeClick()方法。 在onPreferenceTreeClick()方法中可以根据preference的key做事件拦截&#xff0c;如…

Linux线程实用场景

文章目录 前言生产者消费者模型1.基于阻塞队列特点实现使用 2.基于环形队列和信号量实现使用 读者写者模型实现思想 线程池实现 前言 生产者消费者模型和读者写者模型这些模型是用于在线程间协调和管理资源访问的模式, 我们在之前已经理解了线程的概念以及同步与互斥, 现在我们…

无人机之消费级和工业级,两者区别分析

消费级无人机和工业级无人机在多个方面存在显著差异&#xff0c;这些差异主要体现在搭载设备、应用领域、针对用户、使用条件、性能要求、营销模式以及价格等方面。以下是对两者区别的详细分析&#xff1a; 1. 搭载设备 消费级无人机&#xff1a;主要搭载相机&#xff0c;并配…

C++ | Leetcode C++题解之第337题打家劫舍III

题目&#xff1a; 题解&#xff1a; struct SubtreeStatus {int selected;int notSelected; };class Solution { public:SubtreeStatus dfs(TreeNode* node) {if (!node) {return {0, 0};}auto l dfs(node->left);auto r dfs(node->right);int selected node->val…

Windows禁止应用联网

转自两种方法阻止电脑上的软件彻底联网&#xff01; - 知乎 (zhihu.com) 但为了稳妥&#xff0c;自己还是稍微记录一下 1、创建bat脚本文件 创建文本-将下面的代码填入-保存为.bat文件 Echo Off SetLocal:beginecho: echo ****** 禁止文件夹联网 ****** echo:set /p folder…

Qt报“libpng warning: iCCP: known incorrect sRGB profile”问题解决方法

Qt开发应用程序&#xff0c;界面加载图片或按钮加载图标时&#xff0c;会遇到编译器报“libpng warning: iCCP: known incorrect sRGB profile”问题&#xff0c;原因为色彩配置问题&#xff0c;需要修正图像的ICC配置文件&#xff0c;将其转换成sRGB类型。不同操作系统解决方法…

停车场拓扑(parking lot topology)中的 bbr 与 aimd

bbr 讨论组有个有趣的问题&#xff1a;[bbr-dev] Parking lot topology 我此前也意识到这个问题(参见 pacing 之对错)&#xff0c;但几乎所有 cc 的建模都基于 dumbbell topology&#xff0c;parking lot topology 因其太 “不理想”&#xff0c;“不规则” 而无人讨论&#x…

11.2.软件系统分析与设计-数据库分析与设计

文章目录 数据库分析与设计步骤ER图和关系模型 需求分析阶段概念结构设计逻辑结构设计物理结构设计数据库实施与运维 数据库分析与设计 数据库设计属于系统设计的范畴。通常把使用数据库系统的系统统称为数据库应用系统&#xff0c;把对数据库应用系统的设计简称为数据库设计。…

轻松拿捏自动添加好友

释放双手&#xff0c;一键导入数据&#xff01; 通过好友后可以自动备注 轻松自动添加好友&#xff0c;更可以个性化设置验证信息 手动点击“开始”&#xff0c;后台可以看到数据使用情况和添加情况&#xff0c;频繁了会自动停止

【STM32】ADC模拟数字转换(规则组多通道)+ DMA数据转运(外设到存储器)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 前言 ADC规则组扫描模式DMA 定义变量 规则组配置 ADC初始化 连续模式 扫描模式 规则组通道个数 ADC初始化框架 DMA初始化 ADC和DMA使能 软件触发转运 代码框架 ADC扫描转换与DM…

一眼心动的HAProxy高级功能配置

目录 一.haproxy-基于cookie的会话保持 二.七层IP透传 三.四层IP透传 四.访问控制列表ACL 五.acl做动静分离访问控制 六.基于自定义的错误页面文件 七.HAProxy 四层负载 八.HAProxy https 实现 九.让文件编写更简单的方法 一.haproxy-基于cookie的会话保持 cookie va…