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


    相关阅读

    总线协议icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12452508.html?spm=1001.2014.3001.5482


    4、UART接收器

            UART接收器负责接收串行比特流,去除起始位和停止位,并以并行格式将数据保存到与主机数据总线相连的寄存器里。接收器无法获得发送时钟,因此尽管数据以标准比特率到达,但数据未必与接收主机内的时钟同步。同步问题可以用同步器等方法解决,数据的采集可以使用一个更高频率的本地时钟进行采样。为保证采样是在比特时间的中间进行,应对Sample_clock时钟周期进行计数,如下图所示。采样方法必须保证:(1)能够检测到起始位到达;(2)能够采样到8个数据位;(3)能够把采样数据送到本地总线。

            虽然可以采用更高的采样频率,但本例中Sample_clock的频率定为(已知)发送时钟频率的8倍。这可以保证Sample_clock前沿与起始位之间的少许差异不会影响采样,因为只需在起始位对应的比特时间之内采样完成即可。具体来说,就是当串行输入被采样为低电平后表示起始位到来,而后将再进行三次采样增加可信度,在此后的连续数据位都将在比特时间的中间附近被采样(即控制两次采样间隔时间是比特时间),这是通过数据通路中的计数器来实现的。

            下图给出了接收器的内部框图,包括控制单元和数据通路,可以看到其中控制单元和主机之间的接口信号,已经控制单元和数据通路之间的控制信号与状态信号。

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

            read_not_ready_in:表示主机未准备好接收。

            Ser_in_0:当Serial_in = 0时有效,是由数据通路提供的状态信号。

            SC_eq_3:当Sample_counter = 3时有效,是由数据通路提供的状态信号。

            BC_er_8:当Sample_count < 7时有效,是由数据通路提供的状态信号。

            Sample_counter:对两次采样间隔进行计数。

            Bit_counter:计数已采样的数据位数。

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

            read_not_ready_out:表示接收机已接收到8位数据。

            clr_Sample_counter:控制数据通路的Sample_counter计数器清零。

            inc_Sample_counter:控制数据通路的Sample_counter计数值加1。

            clr_Bit_counter:控制数据通路的Bit_counters计数器清零。

            inc_Bit_counter:控制数据通路的Bit_counters计数值加1。

            shift:控制数据通路的RCV_shftreg向LSB方向移位。

            load:控制数据通路的RCV_shftreg数据传送到RCV_datareg。

            Error1:最后一个数据位采样结束后主机还没有准备好接收数据时有效。

            Error2:停止位丢失时有效。

            接收器控制器状态机ASMD如下图所示。该状态机包括idle、starting和receiving三个状态。状态之间的转移由Sample_clk来同步。低有效的同步复位输入rst_b使状态机进入idle状态,直到状态信号Ser_in_0变为高电平(串行输入为0)后状态机进入starting状态。在starting状态下,状态机重复采样Serial_in以确认是否是有效起始位。在Sample_clock的下一个有效沿,clr_Sample_counter和inc_Sample_counter需根据采样值确认是增加计数值还是清零:若接下来的连续三次采样值均为0,则认定为有效起始位,状态机转移到receiving状态并将给出clr_Sample_counter信号控制Sample_counter清零。在receiving状态下inc_Sample_counter将控制Sample_counter计数值增加以进行8个时钟周期的计时,对每个有效比特,在其比特时间的中间采样,总共采样7位数据位,1位校验位,Bit_counter增加。若采样的不是校验位,则inc_Bit_counter和shift持续有效。信号shift有效时,串行输入将载入接收器的移位寄存器RCV_shftreg的MSB位,且寄存器最左边的7位将向LSB方向移动。

    1. module UART_RCVR #(parameter word_size = 8, half_word = word_size / 2)(
    2. output [word_size - 1 : 0]RCV_datareg,
    3. output read_not_ready_out,
    4. Error1, Error2,
    5. input Serial_in,
    6. read_not_ready_in,
    7. Sample_clk,
    8. rst_b
    9. );
    10. wire Ser_in_0, SC_eq_3, SC_lt_7, BC_eq_8,
    11. clr_Sample_counter, inc_Sample_counter,
    12. clr_Bit_counter, inc_Bit_counter,
    13. shift, load;
    14. Control_Unit M0(read_not_ready_out, Error1, Error2, clr_Sample_counter,
    15. inc_Sample_counter, clr_Bit_counter, inc_Bit_counter,
    16. shift, load, read_not_ready_in, Ser_in_0, SC_er_3,
    17. SC_lt_7, BC_er_8, Sample_clk, rst_b);
    18. Datapath_Unit M1(RCV_datareg, Ser_in_0, SC_eq_3, SC_lt_7, BC_eq_8, Serial_in,
    19. clr_Sample_counter, inc_Sample_counter, clr_Bit_counter,
    20. inc_Bit_counter, shift, load, Sample_clk, rst_b);
    21. endmodule
    22. module Control_Unit #(parameter word_size = 8, half_word = word_size / 2,
    23. Num_state_bits = 2)(
    24. output reg read_not_ready_out,
    25. Error1, Error2, clr_Sample_counter,
    26. inc_Sample_counter, clr_Bit_counter, inc_Bit_counter,
    27. shift, load
    28. input read_not_ready_in, Ser_in_0, SC_er_3,
    29. SC_lt_7, BC_er_8, Sample_clk, rst_b
    30. );
    31. localparam idle = 2'b00,
    32. starting = 2'b01,
    33. receiving = 2'b10;
    34. reg [word_size - 1 : 0] RCV_shftreg;
    35. reg [Num_state_bits - 1 : 0] state, next_state;
    36. always@(posedge Sample_clk)
    37. if(rst_b == 0)
    38. state <=idle;
    39. else
    40. state <= next_state;
    41. always@(*)begin
    42. read_not_ready_out = 0;
    43. clr_Sample_counter = 0;
    44. clr_Bit_counter = 0;
    45. inc_Sample_counter = 0;
    46. inc_Bit_counter = 0;
    47. shift = 0;
    48. Error1 = 0;
    49. Error2 = 0;
    50. load = 0;
    51. next_state = idle;
    52. case(state)
    53. idle: if(Ser_in_0 == 1)
    54. next_state = starting;
    55. else
    56. next_state = idle;
    57. starting: if(Ser_in_0 == 0)begin
    58. next_state = idle;
    59. clr_Sample_counter = 1;
    60. end
    61. else if(SC_eq_3 == 1)begin
    62. next_state = receiving;
    63. clr_Sample_counter = 1;
    64. end
    65. else begin
    66. next_state = starting;
    67. inc_Sample_counter = 1;
    68. end
    69. receiving: if(SC_lt_7 == 1)begin
    70. inc_Sample_conter = 1;
    71. next_state = receiving;
    72. end
    73. else begin
    74. clr_Sample_counter = 1;
    75. if(!BC_eq_8)begin
    76. next_state = receiving;
    77. shift = 1;
    78. inc_Bit_counter = 1;
    79. end
    80. else begin
    81. next_state = idle;
    82. read_not_ready_out = 1;
    83. clr_Bit_counter = 1;
    84. if(read_not_ready_in == 1)
    85. Error1 = 1;
    86. else if(Ser_in_0 == 1)
    87. Error2 = 1;
    88. else
    89. Load = 1;
    90. end
    91. end
    92. default: next_state = idle;
    93. endcase
    94. end
    95. endmodule
    96. module Datapath_Unit #(parameter word_size = 8, half_word = word_size / 2,
    97. Num_counter_bits = 4)(
    98. output reg [word_size - 1 : 0] RCV_datareg,
    99. output Ser_in_0,SC_eq_3, SC_lt_7, BC_eq_8,
    100. input Serial_in, clr_Sample_counter, inc_Sample_counter, clr_Bit_counter,
    101. inc_Bit_counter, shift, load, Sample_clk, rst_b
    102. );
    103. reg [word_size - 1 : 0] RCV_shftreg;
    104. reg [Num_counter_bits - 1 : 0] Sample_counter;
    105. reg [Number_counter_bits : 0] Bit_counter;
    106. assign Ser_in_0 = (Serial_in == 0);
    107. assign BC_eq_8 = (Bit_counter == word_size);
    108. assign SC_lt_7 = (Sample_counter < word_size - 1);
    109. assign SC_eq_3 = (Sample_counter == half_word - 1);
    110. always@(posedge Sample_clk)
    111. if(rst_b == 0)begin
    112. Sample_counter <= 0;
    113. Bit_counter <= 0;
    114. RCV_datareg <= 0;
    115. RCV_shftreg <= 0;
    116. end
    117. else begin
    118. if(clr_Sample_counter == 1)
    119. Sample_counter <= 0;
    120. else if(inc_Sample_counter == 1)
    121. Sample_counter <= Sample_counter + 1;
    122. if(clr_Bit_counter == 1)
    123. Bit_counter <= Bit_counter;
    124. else if(inc_Bit_counter == 1)
    125. Bit_counter <= Bit_counter + 1;
    126. if(shift == 1)
    127. RCV_shftreg <= {Serial_in, RCV_shftreg[word_size - 1 : 1]};
    128. else if(load == 1)
    129. RCV_datareg <= RCV_shftreg;
    130. end
    131. endmodule

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

  • 相关阅读:
    【项目测试报告】博客系统 + 在线聊天室
    大数据-玩转数据-Flume
    详细解决:Swagger API 未授权访问漏洞问题
    C++ 不知图系列之基于链接表的无向图最短路径搜索
    为啥装了erlang,还报错erl: command not found?
    Python的数据分析包Pandas?示例文章完成版来啦~
    ansible安装教程
    kernel32.dll下载地址分享,Kernel32.DLL文件丢失的修复指南
    【numpy】numpy.where的使用
    Elasticsearch部署中的两大常见问题及其解决方案
  • 原文地址:https://blog.csdn.net/weixin_45791458/article/details/133302686