通信协议:Uart的Verilog实现(上)

news2024/12/25 0:29:59

1、前言

        调制解调器是主机/设备与串行数据通路之间的接口,以串行单比特格式发送和接收数据。它也被称为通用异步收发器(Uart, Universal Asynchronous Receiver/Transmitter),这表明该设备能够接收和发送数据,并且发送和接收单元不同步。

        本节中,UART以ASCII码的格式交换文本数据,在ASCII码格式中,每一帧包含1位起始位,5-8位数据位,1位可选的奇偶校验位和1位停止位。在本文的实现中,使用了了7位数据,因此数据格式如下所示。发送时从起始位(低位)开始,向高位逐位发送,每个位持续一个时钟周期(比特位时间),停止位的有效时间则可能会超过一个时钟周期,即两帧之间的间隔可以是多个时钟周期。

停止位校验位数据位6数据位5数据位4数据位3数据位2数据位1数据位0起始位

Uart传送的ASCII文本数据格式

2、UART的操作

        UART发送器通常是更大系统的一部分,其主机以并行格式取出数据并指定UART以串行格式发送。UART接收器需检测传输情况,以串行格式接收数据,去掉起始位和停止位后以并行格式存储数据。因为远程接收器无法得到数据发送时钟——数据异步到达,接收器会比发送器更复杂。接收器必须重新产生本地时钟而不是用发送时钟来同步数据采样。

        UART的简化结构如下图所示,图中给出了主机用于控制UART以及从数据总线接收或发送数据的信号,但没有给出主机的细节。

3、UART发送器

        下面的框图给出了发送器的输入/输出信号。输入信号由主机提供,包括(Load_XMT_datareg, Byte_ready, T_byte, Data_Bus)而输出信号包括串行数据流(Serial_out)。发送器由控制单元和数据通路构成,控制单元是一个FSM,用于给出控制信号给数据通路;而数据通路包含数据寄存器(XMT_datareg)、数据移位寄存器(XMT_shftreg)和用于计数已发送比特数的状态寄存器(bit_count)。状态寄存器包含在数据通路中。

        发送器的内部信号如下所列。注意,信号Load_XMT_datareg本可以直接送至数据通路,但这里将其送入控制器并在idle状态下根据该信号对Load_XMT_DR进行条件赋值。

        控制单元的输入信号及其作用:

        Load_XMT_datareg:idle状态下由其决定Load_XMT_DR信号的值(用于控制将Data_Bus的内容载入XMT_data_reg)。

        Byte_ready:由其决定Load_XMT_shftreg信号的值(用于控制将XMT_data_reg中的内容载入XMT_shftreg)。

        T_byte:用于决定一帧数据传输的开始(将串行输出拉低)。

        BC_lt_BCmax:用于指示数据移位还未完成(即Bit_count < word_size + 1)。

        控制单元的输出信号及其作用:

        Load_XMT_DR:控制Data_Bus的内容载入XMT_data_reg。

        Load_XMT_shftreg:控制将XMT_data_reg中的内容载入XMT_shftreg。

        Start:控制将XMT_shftreg[0]清零表示输出起始位,传输开始。

        Shift:控制将XMT_shftreg右移一位,并在高位补1(停止位)。

        Clear:控制将bit_count清零。

        发送器控制器的状态机ASMD图如下图所示。该状态机包括idle、waiting和sending三个状态。当低有效的同步复位信号rst_b有效时,状态机进入idle状态,同时bit_count被清零,XMT_shftreg被1填充。在idle状态下,主机在令Load_XMT_datareg有效后,控制器输出信号Load_XMT_DR将Data_bus上的内容载入XMT_data_reg。状态机保持idle状态直到主机使Load_XMT_datareg无效并使Byte_ready信号有效,这时会输出Load_XMT_shftreg并进入waiting状态。Load_XMT_shftreg会控制XMT_datareg中的内容载入XMT_shftreg的最左边的比特位,同时令LSB为1(停止位)。

        T_byte有效后输出start信号,下个时钟沿,状态机进入sending状态,同时XMT_shftreg的LSB清零。此时只要计数值未满,sending状态下会一直输出shift信号,这使得XMT_shftreg的数据右移并高位补1。当计数满时(BC_lt_BCmax==0)时,clear信号有效,表示所有有效数字已输出,此时正在输出最后一位停止位,在下一个时钟沿状态机返回idle状态。

        下面给出UART_XMTR的Verilog HDL描述:

module UART_XMTR #(parameter word_size = 8)(
    output Serial_out,     //Serial output ti data channel
    input [word_size - 1 : 0] Data_Bus, //Host data bus containing data word
    input Load_XMT_datareg,             //Used by host to load the data register
          Byte_ready,                   //Used by host to signal ready
          T_byte,                  //Used by host to signal start of transmission
          Clock,                   //Bit clock of the transmitter
          rst_b                    //Resets internal registers, loads the             
                                   //XMT_shftreg with ones 
);

wire BC_lt_BCmax;
wire Load_XMT_DR;
wire Load_XMT_shftreg;
wire start;
wire shift;
wire clear;

Controller_Unit M0(
    Load_XMT_DR, Load_XMT_shftreg, start, shift, clear, Load_XMT_datareg,
    Byte_ready, T_byte, BC_lt_BCmax, Clock, rst_b);

Datapath_Unit M1(
    Serial_out, BC_lt_BCmax, Data_bus, Load_XMT_DR, Load_XMT_shftreg,
    start, shift, clear, Clock, rst_b);

endmodule

module Control_Unit #(
    parameter one_hot_count = 3,  //Numbers of one-hot states
              state_count = one_hot_count, //Number of bits in state register
              size_bit_count = 3 //Size of the bit counte
)(
    output reg Load_XMT_DR,  //Loads Data_Bus into XMT_datareg
               Load_XMT_shftreg, //Loads XMT_datareg into XMT_shftreg
               start,        //Launches shifting of bits in XMT_shftreg
               shift,        //Shift bits in XMT_shftreg
               clear,        //Clears bit_count after last bit is sent
    input Load_XMT_datareg,  //Asserts Load_XMT_DR in state idle
          Byte_ready,        //Asserts Load_XMT_shftreg in state idle
          T_byte,            //Asserts start signal in state waiting
          BC_lt_BCmax,       //Indicates status of bit counter 
          Clock,
          rst_b
);

    localparam idle = 3'b001,
               waiting = 3'b010,
               sending = 3'b100,
               all_ones = 9'b1_1111_1111;

    reg [state_count - 1 : 0] 	state, next_state;  // State machine controller
    
    always@(*)begin
        Load_XMT_DR = 0;
        Load_XMT_shftreg = 0;
        start = 0;
        clear = 0;
        shift = 0;
        next_state = idle;
        case(state)
            idle: if(Load_XMT_datareg == 1'b1)begin
                      Load_XMT_DR = 1;
                      next_state = idle;
                  end
                  else if(Byte_ready == 1'b1)begin
                      Load_XMT_shftreg = 1;
                      next_state = waiting;
                  end
            waiting: if(T_byte == 1)begin
                         start = 1;
                         next_state = sending;
                     end
                     else next_state = waiting;
            sending: if(BC_lt_BCmax == 1)begin
                         shift = 1;
                         next_state = sending;
                     end
                     else begin
                         clear = 1;
                         next_state = idle;
                     end
            default: next_state = idle;
        endcase
    end

    always@(posedge Clock, negedge rst_b)begin
        if(rst_b == 0) 
            state <= idle;
        else
            state <= next_state;
    end
endmodule

module Datapath_Unit #(
    parameter word_size = 8,
    size_bit_count = 3
)(
    output Serial_out,
           BC_lt_BCmax,
    input [word_size - 1 : 0] Data_bus,
    input Load_XMT_DR,
          Load_XMT_shftreg,
          start,
          shift,
          clear,
          Clock,
          rst_b
);

    localparam all_ones = 9'b1_1111_1111;

    reg [word_size - 1 : 0] XMT_datareg; //Transmit Data Register
    reg [word_size : 0] XMT_shftreg;     //Transmit Shift Register
    reg [size_bit_count : 0] bit_count;  //Counts the bits that are transmitted

    assign Serial_out = XMT_shftreg[0];
    assign BC_lt_BCmax = (bit_count < word_size + 1);

    always@(posedge Clock, negedge rst_b)
        if(rst_b == 0)begin
            XMT_shftreg <= all_ones;
            bit_count <= 0;
        end
        else begin
            if(Load_XMT_DR == 1)
                 XMT_datareg <= Data_bus;  //Get the data bus
            if(Load_XMT_shftreg == 1)
                 XMT_shftreg <= {XMT_datareg, 1'b1};//Load shift reg, insert stop             
                                                    //bit
            if(start == 1)XMT_shftreg[0] <= 0;      //Signal start of transmission
            if(clear == 1)bit_count <= 0;
            if(shift == 1)begin
                XMT_shftreg <= {1'b1, XMT_shftreg[word_size : 1]};//Shift right, 
                                                                 //fill with ones
                bit_count <= bit_count + 1;
            end
        end
endmodule

以上内容来源于《Verilog HDL高级数字设计》,有删改

        

        

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

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

相关文章

Python项目实战:基于2D或3D的区域增长算法

文章目录 一、简介二、项目实战2.1、2D图像&#xff08;10x10&#xff09;2.2、2D图像&#xff08;100x100&#xff09;2.3、3D图像&#xff08;10x10x10&#xff09; 一、简介 区域增长算法是一种用于图像分割方法&#xff0c;将相邻像素按照一定的相似性合并成一个区域。 步…

Spring 学习(九)整合 Mybatis

1. 整合 Mybatis 步骤 导入相关 jar 包 <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency>…

规模化、可复制的大模型应用——企业知识管家

9月18日&#xff0c; “2023可信AI大会暨南京人工智能产业发展大会大模型高质量发展分论坛”在南京成功举办&#xff0c;九章云极DataCanvas公司受邀出席论坛&#xff0c;和与会嘉宾共同探讨大模型时代企业知识管理面临的挑战和机遇&#xff0c;同时作为大模型创新与应用代表企…

每日一题2023.9.25|LeetCode1367.二叉树中的链表

1367.二叉树中的链表 链接&#xff1a;LeetCode1367.二叉树中的链表 错误分析 其实这道题目思路很简单&#xff1a; 采用前序遍历的方式从根节点开始遍历二叉树&#xff0c;并在遍历的过程中比较与链表节点的值是否相等&#xff0c;如果当前链表节点的值和树节点的值相等&am…

怎样提高外贸业务销售能力

怎样提高外贸业务销售能力 一、市场分析与研究1. 了解目标市场&#xff1a;2. 收集客户信息&#xff1a; 二、产品知识和差异化竞争1. 熟悉产品&#xff1a;2. 差异化竞争&#xff1a; 三、制定销售策略和计划1. 制定销售计划&#xff1a;2. 销售策略&#xff1a; 四、谈判技巧…

Python开发与应用实验2 | Python基础语法应用

*本文是博主对学校专业课Python各种实验的再整理与详解&#xff0c;除了代码部分和解析部分&#xff0c;一些题目还增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人自己的补充&#xff0c;以方便大家额外学习、参考。 &a…

Wespeaker框架训练(1)

1. 数据集准备(Data preparation) 进入wespeaker目录文件/home/username/wespeaker/examples/voxceleb/v2 对run.sh文件进行编辑 vim run.sh 可以看到run.sh里面的配置内容 #数据集下载&#xff0c;解压 stage1 #插入噪音&#xff0c;制作音频文件 stop_stage2 #数据集放置…

如何重装Windows Mirosoft Store

重装Windows Mirosoft Store 如何重装Windows Mirosoft Store呢&#xff1f;如何下载Windows Mirosoft Store呢&#xff1f;Windows Mirosoft Store不见了咋办&#xff1f;Windows 自带软件不见了咋办等等&#xff1f;写在前面 1.文件准备2.安装 如何重装Windows Mirosoft Stor…

Java之序列化的详细解析

3. 序列化 3.1 概述 Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象&#xff0c;该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后&#xff0c;相当于文件中持久保存了一个对象的信息。 反之&#xff0c;该字节…

vue做无缝滚动

类似于这种&#xff1a; 以上截图来自于官网&#xff1a;vue-seamless-scroll 具体使用步骤为&#xff1a; 1:安装 cnpm install vue-seamless-scroll --save  2&#xff1a;引入 <vue-seamless-scroll></vue-seamless-scroll>import vueSeamlessScroll from …

最熟悉的陌生人!Java运算符详解

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、算术运算符1、四则运算符2、增量运算符3、自增、自减运算符 二、关系运算符三、关系运算符1、逻辑与 &&2、逻辑或|…

【PDF提取页面】使用Adobe Acrobat提取PDF文档的某几个页面另存

▚ 01 使用Adobe Acrobat打开目标文件 ▚ 02 打开 ->页面缩略图Page Thumbnails ▚ 03 右键选择 -> 提取页面 Extract Pages… ▚ 04 选择提取的页数范围 &#x1f341; 一般设置提取页面的初始位置和截至位置即可。 ▚ 05 将提取的目标页面另存为->新PDF文

基于微信小程的流浪动物救助宠物领养平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

05_JavaScript基本语法

1 变量 1.1 标识符 程序开发中&#xff0c;经常需要自定义一些符号来标记一些名称&#xff0c;并赋予其特定的用途&#xff0c;如变量名、函数名等&#xff0c;这些符号都被称为标识符。 定义规则 由大小写字母&#xff08;A-Z,a-z&#xff09;、数字&#xff08;0-9&#…

[docker]笔记-网络故障处理

1、同事在虚拟机上部署docker&#xff0c;发现电脑无法登录虚拟机了。首先ping测是通的&#xff0c;从我电脑继续进行登录测试发现没问题&#xff0c;初步判断是她电脑网络和虚拟机网络之间连接出错。 2、进行虚拟机登录查看&#xff0c;首先使用route -n命令查看路由&#xf…

Java深入理解线程的三大特性

目录 1 CPU缓存导致可见性问题2 线程切换导致原子性问题3 性能优化导致有序性问题4 JMM(Java Memory Model)5 volatile6 synchronized 1 CPU缓存导致可见性问题 线程的三大特性&#xff1a; 可见性&#xff1a;Visibility有序性&#xff1a;Ordering原子性&#xff1a;Atomic…

YApi Pro

1.介绍 说明&#xff1a;YApi Pro 是一款高效、易用、功能强大的 API 管理平台&#xff0c;旨在为开发、产品、测试人员提供更优雅的接口管理服务。它可以帮助开发者轻松创建、发布、维护 API&#xff0c;同时为用户提供了优秀的交互体验&#xff0c;开发人员可以更加高效地完…

【面试算法——动态规划 19】最长回文子序列 (hard)让字符串成为回文串的最少插入次数

516. 最长回文子序列 链接: 516. 最长回文子序列 给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。 示例 1&…

C语言实现八种功能的通讯录(添加、删除、查找、修改、显示、排序、退出、清空)

通讯录功能概要及前提说明 此通讯录利用C语言完成&#xff0c;可以实现八种功能的通讯录&#xff08;添加、删除、查找、修改、显示、排序、退出、清空&#xff09; 代码由三部分组成&#xff0c;为什么要写成三部分而不写成一部分可以参考我以前的博客&#xff0c;如下&…

【Linux】Linux多线程

怎么理解线程线程的优缺点线程的二级页表线程用途怎么管理线程线程创建获取创建后的ID方法 线程等待线程终止分离线程线程ID及进程地址空间布局 怎么理解线程 通俗易懂的说&#xff0c;线程的运行是必须有进程给它打个基础。线程的运行是服用进程的代码及空间来进行运作的。 那…