00 简介uart接收数据部分是接收另一个串口设备发送的数据,缓存到接收fifo中。fifo快要写满时,产生中断通知cpu拿取数据,实现串口数据的接收。
模块涉及到两个时钟域,arm时钟和26mhz功能时钟。其中 接收fifo读写逻辑是arm时钟域,接收数据状态机和同步逻辑等是功能时钟域 。
01 模块接口与描述
02 实现uart_rx模块主要由三部分组成: 配置信息同步 、接收状态机和 接收数据fifo控制 。
配置信息是reg_if模块由apb总线配置寄存器产生,功能时钟域做两级同步处理。
接收状态机是根据串口协议划分,分为idle、start、rx_data、check_data、stop和send六种状态。
接收数据fifo控制部分将接收完成的数据写入到fifo,在cpu读取rx_fifo寄存器时将fifo数据读出送到rx_fifo寄存器。
配置信息同步由于配置信息是由arm时钟产生,到接收模块的功能时钟域需要做同步处理。配置信息是电平信号,通常不会像数据一样变化快,所以只需要两级同步。
接收状态产生接收数据停止位状态指示st_error和接收数据校验位状态指示p_error是串口校验位和停止位检测状态指示。前者为1表示停止位错误;后者为1表示校验位错误。两个状态位都会传到reg_if模块,指示urat当前状态,供cpu查询。当cpu发现停止位或者校验位错误时,会决定当前数据的处理方式(丢弃或者接受),清除状态位(即写1清0)。reg_if模块发现该状态位清除后,会回送一个ack到接收模块,即st_error_ack和p_error_ack。接收模块接收到ack后释放状态指示st_error和p_error,继续接收数据。
这个过程就是状态位的握手,本模块设计方式是握手期间,即发现校验位或者停止位错误后停止接收数据,直到cpu清除状态后才开始正常接收。读者可以根据自己的需要判断错误后是否继续接收数据。
接收状态机使用典型的三段式状态机设计,包含六种状态,idle、start、rx_data、check_data、stop和send。
uart接收状态转移图
idle:状态机从idle状态开始,检测到uart_i的下降沿,进入start状态。
start:start状态起始位是否为低(避免毛刺触发状态机),起始位正常即进入rx_data开始接收数据。rx_data:接收满8bit后判断是否使能校验位,如使能,进入check_data状态进行奇偶校验的判断;如不使能,直接进入停止状态stop。
check_data:check_data状态判断奇偶校验是否正确,不正确则发出p_error信号,在状态寄存器指示校验错误,待cpu处理返回p_error_ack后回到idle状态。如果正确,判断是否使能停止位检查;使能停止位检查则跳转到stop状态;不使能则跳转到send状态。
stop:同样的,在stop状态检测停止位是否是高电平。如果是,表示停止位正确,跳转到send状态;如果不是,则发出st_error信号,在状态寄存器指示停止位错误,待cpu处理返回st_error_ack后回到idle状态。
send:send状态主要是产生rx_start信号表示8bits数据接收正确,可以将数据写到接收fifo。
前两段状态机,状态跳转:
// state to nextstate with clk in this block.always@(posedge clk26m ornegedge rst26m_)begin if(!rst26m_) begin state <= idle; end elsebegin state <= nextstate; endend// nextstate transformalways@(*) begin case(state) idle: begin if(neg_urxd_i) begin nextstate = start; end elsebegin nextstate = idle; end end start: begin if(start_right) begin// start bit is right,then reserve data nextstate = rx_data; end elsebegin nextstate = idle; end end rx_data: begin if(data_cnt < 4'd8) begin// reserve 8 datas nextstate = rx_data; end elsebegin if(rx_bpsclk) begin if(check_syn2) begin nextstate = check_data; end elsebegin nextstate = stop; end end elsebegin nextstate = rx_data; end end end check_data: begin if(p_error_ack_delay2) begin nextstate = idle; end elsebegin if(rx_bpsclk) begin // p_error:1:parity bit error,0:parity bit error if(p_error) begin nextstate = check_data; end elsebegin // st_check:1:check stop bit,0:don't check stop bit if(st_check_syn2) begin nextstate = stop; end elsebegin nextstate = send; end end end elsebegin nextstate = check_data; end end end stop: begin if(st_error_ack_delay2) begin nextstate = idle; end elsebegin if(rx_bpsclk) begin // st_error:1:stop bit error,0:stop bit error if(st_error) begin nextstate = stop; end elsebegin nextstate = send; end end elsebegin nextstate = stop; end end end send: begin if(rx_ack_delay2) begin nextstate = idle; end elsebegin nextstate = send; end end default: begin nextstate = idle; end endcaseend第三段状态机,信号赋值:
// output signal statealways@(posedge clk26m ornegedge rst26m_) begin if(!rst26m_) begin rx_bpsen <= 1'b0; data_rx <= 8'd0; data_cnt <= 4'd0; p_error <= 1'b0; st_error <= 1'b0; rx_start <= 1'b0; start_right <= 1'b0; end elsebegin case(nextstate) idle: begin rx_bpsen <= 1'b0; data_cnt <= 4'd0; st_error <= 1'b0; p_error <= 1'b0; rx_start <= 1'b0; start_right <= 1'b0; end start: begin rx_bpsen <= 1'b1; if(rx_bpsclk) begin if(urxd_i == 1'b0) begin start_right <= 1'b1; end elsebegin start_right <= 1'b0; end end end rx_data: begin if(rx_bpsclk) begin data_rx[data_cnt] <= urxd_i; data_cnt <= data_cnt + 1'b1; end end check_data: begin if(rx_bpsclk) begin // odd check if(parity_syn2) begin if(^data_rx == urxd_i) begin// odd check is wrong p_error <= 1'b1; rx_bpsen <= 1'b0; end end // even check elsebegin if(^data_rx == !urxd_i) begin// even check is wrong p_error <= 1'b1; rx_bpsen <= 1'b0; end end end end stop: begin if(rx_bpsclk) begin if(urxd_i == 1'b0) begin// stop bit is wrong st_error <= 1'b1; rx_bpsen <= 1'b0; end end end send: begin rx_start <= 1'b1; end endcase endend接收数据fifo控制接收状态机的send状态表示1byte数据接收完成,此状态会产生一个rx_start信号。
fifo写控制部分通过监控此信号产生写使能rx_fifo_winc(1个arm时钟周期)和接收响应rx_ack,send状态发现rx_ack后释放rx_start,回到idle状态。由于fifo写控制是在arm时钟域进行,握手的时间很短,不会对接收下一byte数据产生影响。
// this state machine to send data to rx fifoalways@(posedge clk ornegedge rst_) begin if(!rst_) begin rx_ack <= 1'b0; rx_fifo_winc <= 1'b0; wdata_state <= 2'b0; end elsebegin case(wdata_state) 2'b00: begin if(!rx_fifo_wfull && rx_start_delay2) begin rx_ack <= 1'b1; rx_fifo_winc <= 1'b1; wdata_state <= 2'b01; end end 2'b01: begin rx_fifo_winc <= 1'b0; if(!rx_start_delay2) begin rx_ack <= 1'b0; wdata_state <= 2'b10; end end 2'b10: begin wdata_state <= 2'b0; end endcase endendfifo读逻辑放在reg_if模块,apb读rx_data寄存器时,产生读使能信号,fifo将数据放到寄存器中。
深度解读汽车电动助力转向系统扭矩传感器技术
云计算存储虚拟化技术三个层次上的实现
基于MediaTek Genio350的智能烤箱方案
压电陶瓷片的工作原理
日立增强版分析软件提高工作流程效率
如何实现串口数据的接收呢?
如何警惕以区块链为名的诈骗
可穿戴设备对驾驶员监测系统的冲击
西方冷、东方热,FD-SOI准备大赚IoT商机
探索VR技术如何重塑多个行业
负反馈电路案例
3D建模三维扫描钢琴乐器扫描复刻逆向工程设计服务
联想得来不易的反弹,网络舆论对中国企业影响甚大
基于机器视觉技术的连接器缺陷特征检测
有关钠离子电池的详细解读
汽车连接器的三种故障模式
沃趣科技受邀参与第24届中国科博会-科创企业首席技术官交流会
解决雷达和通信系统中的相位噪声挑战
Vishay发布IHLE集成电场屏蔽电感器 高通和法拉利达成战略合作
传感器监测系统在土壤墒情监测中的应用