本文为明德扬原创文章,转载请注明出处! 串口吸收模块的功效:吸收上位机通过串口发送过来的数据,举行串并转换之后送给下游模块。注:串口波特率9600,无奇偶校验位。一、设计架构上图是与上位机通信的串口的时序图。我们从图中可以获取到如下关键信息。
1. 串口数据线位宽为1bit,默认状态下为高电平。2. 每次上游模块发送数据,都是先发送1位的起始位0,然后发送8位的数据,最后是1位的停止位1。3. 每1位所占的时间,可以通过波特率来盘算。盘算方法如下: 波特率是指1s内发送或接受了几多比特数据,若波特率为9600 bit/s,则1s可以传输9600bit,那么传输1bit的时间为:1/9600(s)。
以mp801开发板为例,时钟频率为50M,那么发送1bit就需要5208个时钟周期。串口吸收模块接纳两个计数器的架构,这两个计数器划分表现吸收1bit需要的时间和共需要吸收几多bit。其结构图如下: 计数器cnt0:对吸收1bit数据需要的时间举行计数;吸收1bit需要5208个时钟周期。该计数器的计数周期为5208。
计数器cnt1:对吸收几多bit的数据举行计数;停止位不到场,起始位加上数据位共9bit。该计数器的计数周期为9。本工程使用了检测信号下降沿的方法,信号下降沿的检测方法: 检查uart_rx的下降沿,就要用到FPGA里的边缘检测技术。
所谓的边缘检测,就是检测输入信号,或者FPGA内部逻辑信号的跳变,即上升沿或者下降沿的检测。就好比前面uart_rx由1变0时,就泛起了下降沿,接着一次指令竣事,uart_rx由0变1时,就泛起了上升沿,边缘检测技术这在FPGA电路设计泛。电路图如下: 对应的信号列表如下图所示: 中间信号,trigger连到触发器的信号输入端D,触发器的输出器连的是tri_ff0。
将trigger取反,与tri_ff0相与,就获得信号neg_edge,如果neg_edge=1就表现检测到trigger的下降沿。将tri_ff0取反,与trigger相与,就获得信号pos_edge,如果pos_edge=1,就表现检测到trigger的上升沿。
我们来解说这个原理,信号的波形图如下: Tri_ff0是触发器的输出,因此tri_ff0的信号与trigger信号相似,可是相差了一个时钟周期。我们也可以明白为:每个时钟上升沿看到的tri_ff0的值,其实就是triffer信号上一个时钟看到的值,也就是tri_ff0是trigger之前的值。我们在看第3时钟上升沿,此时trigger值为0,而tri_ff0的值为1,即当前trigger的值为0,之前的值为1,这就是下降沿,此时neg_edge为1。
当看到neg_edge为1,就表现检测到trigger的下降沿了。同理在第7个时钟上升沿,看到trigger值为1,而之前值为0,pos_edge为1,表现检测到trigger的上升沿。
本模块输入信号uart_rx是异步信号,异步信号都需要履历同步化后,才气够使用。异步信号同步化如下。在前面讨论边缘检测的波形中,我们把trigger当做理想的同步信号来思量,也就是trigger满足D触发器的建设和保持时间,在同步系统中实现边缘检测不是问题。
但如果trigger不是理想的同步信号,例如外部按键信号,以及本工程的uart_rx信号。这些信号什么时候发生变化,是外部传输指令给FPGA,对于FPGA来说完全是随机的。
很有可能泛起,信号在时钟上升沿发生变化的情况,从而无法满足触发器的建设时间和保持时间要求,泛起亚稳态的情况,从而导致系统瓦解。如下图,我们先将信号用2个触发器举行了寄存,确定了信号的稳定性,然后再举行边缘检测,告竣了同步系统中实现边缘检测的需求。
那么边缘检测的代码设计就需要先举行触发器的设计,假设输入的信号trigger不是同步信号,要将该信号用2个触发器举行寄存,获得tri_ff0和tri_ff1。需要特别注意的是,在第一个触发器阶段,信号依旧有亚稳态的情况,因此tri_ff0绝对不行以拿来当条件使用,只能使用tri_ff1。接着举行检测边缘,凭据前面所说,得出同步信号后再用寄存器寄存,获得tri_ff2。
凭据tri_ff1和tri_ff2,我们就可以获得边缘检测效果。当tri_ff1==1且tri_ff2==0时,上升沿的pos_edge有效;当tri_ff1==0且tri_ff2==1时,下降沿的neg_edge有效,代码如下:综上所述,如果进来的信号是异步信号,那么就需要先举行同步化,再做检测,即通过打两拍的方式,实现了信号的同步化;再通过打一拍的方式,实现边缘检测电路。反之,如果进来的信号自己就是同步信号,那就没有须要做同步化了,可以直接做边缘检测。二、信号的意义三、参考代码下面展出本模块的设计,接待进一步交流,如果需要整个项目源代码,接待与明德扬联系。
module uart_rx( clk , rst_n , uart_rx , rx_vld , rx_data ); parameter CNT_BTL = 20'd2604; parameter CNT_MID = 20'd1302; parameter CNT_RX = 4'd9; parameter DATA_W = 8; input clk ; input rst_n ; input uart_rx ; wire uart_rx ; output[DATA_W-1:0] rx_data ; output rx_vld ; reg [DATA_W-1:0] rx_data ; reg rx_vld ; reg uart_rx_ff0 ; reg uart_rx_ff1 ; reg uart_rx_ff2 ; reg flag_add_add ; reg [19:0] cnt0 ; wire add_cnt0 ; wire end_cnt0 ; reg [3:0] cnt1 ; wire add_cnt1 ; wire end_cnt1 ; wire add_en ; always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt0 <= 0; end else if(add_cnt0)begin if(end_cnt0) cnt0 <= 0; else cnt0 <= cnt0 + 1; end end assign add_cnt0 = flag_add[size=9.0000pt]; assign end_cnt0 = add_cnt0 && cnt0== CNT_BTL-1; always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt1 <= 0; end else if(add_cnt1)begin if(end_cnt1) cnt1 <= 0; else cnt1 <= cnt1 + 1; end end assign add_cnt1 = end_cnt0; assign end_cnt1 = add_cnt1 && cnt1== CNT_RX-1; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin uart_rx_ff0 <= 1'b1; uart_rx_ff1 <= 1'b1; uart_rx_ff2 <= 1'b1; end else begin uart_rx_ff0 <= uart_rx; uart_rx_ff1 <= uart_rx_ff0; uart_rx_ff2 <= uart_rx_ff1; end end assign add_en = uart_rx_ff2&&~uart_rx_ff1; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin flag_add <= 1'b0; end else if(add_en)begin flag_add <= 1'b1; end else if(end_cnt1)begin flag_add <= 1'b0; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin rx_vld <= 1'b0; end else if(end_cnt1)begin rx_vld <= 1'b1; end else begin rx_vld <= 1'b0; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin rx_data <= 8'b0; end else if(cnt1!=0&&add_cnt0&&cnt0==CNT_MID-1)begin rx_data[cnt1-1] <= uart_rx_r2; end endendmodule。
本文关键词:边缘,检测,工程,串口,吸收,模块,代码,剖析,欧宝官网app客户端下载
本文来源:欧宝app官网登陆-www.dsjx1688.com