当前位置:   article > 正文

FPGA 串口通信(uart)初探篇(含源代码)_fpga uart

fpga uart

一、UART

串口通信,说实话是日常生活中很常见的一种9针型的主机和显示屏之间的通信模式。本次博客,只为自己复盘相关知识,初学者,错误较多,请多指教。所以本文参考(一)FPGA之串口通信(UART)_fpga uart-CSDN博客

而编著的。

FPGA是一种可编程的逻辑器件,用于各种数字电路设计与实现,是一种可重复利用的芯片盒。今天所介绍的是利用赛灵思xc7a35tftg256-1系列的FPGA实现串口通信(UART)。

一个状态机,我们有发送模块(uart_tx)和接收模块((uart_tx)。模块首先得有一个时钟信号CLK,复位信号RESET.

波特率解释:

        串口协议中baud_rate波特率是很重要的知识点,字面意思就是一秒钟传输的码元(即一个0-1状态)的个数,就是指的是一秒钟传输的二进制位数,常见单位是bit/s和bps两种,常见的串口速度有115200bps(RS232串口)和9600bps and so on,

波特率和字节转换:

        1GB=1024MB   1MB=1024KB   1KB=1024B字节  ,倘若我们串口数据位每秒钟512字节,串口的波特率就是115200位/秒   (没搞懂换算?)

如果我们校验位置零,则位/10=字节 ,如波特率115200,即是115200(位/秒)=11520(b/s) ;除以1024 就可以从位换算到KB:波特率115200=115200((位/秒))=11.25KB/S

今天我们要在FPGA上实现异步串口通信,假设我们FPGA的clk时钟是50Mhz的系统时钟,波特率是9600bps,那么传输一个bit需要的时钟周期个数是50_000_000/9600个个数。得到这个个数,再乘以周期时间,就可以得到这个1bit所需要的时间。

状态机工作原理解释:

1.串口通信的信号线只需要两条线就可以完成。tx和rx, tx是状态机信号发送端,rx是状态机的信号接收端。

2.起始位STATE_START,数据线由高变低,低有效触发,即0开始,数据开始传输。

3.数据位,起始位低有效之后,数据位开始传输,如下图是8为数据,从左向右开始传输低位向着高位前进。

4.校验位PARITY,我们可以将校验位当成一个特殊的空位。通常使用的是奇偶校验位,通常在代码中有说明是否有校验, PARITY_ON=0,   //校验位,1为有校验位,0为无校验位,缺省为0。(即在串口通信中,校验位通常不适用)

5.停止位end,高有效=1,它表是一个个字节传输的结束

6.空闲位,是持续的高有效,由于当start=0低电平以后开始数据传输,所以高有效就能够使得状态机处于空闲状态。

7.帧:我们将一个个字节传输从起始位到停止位经历的全部时间称之为一帧。

状态机模型解释:

        如下图,我们定义了一个state状态机,用于控制串口通信的不同状态。我们还定义了一个bit_counter计数器用于计算每个位的延迟时间,在串口通信实例中,假设每个位延迟时间为bit_delay。然后定义一个数据寄存器serial_data,用于存储接收到的数据,开始时置位为0

在状态机的always块中,我们根据不同的状态开始发送以及接收。在空闲状态IDLE下,如果检测到起始位,则将状态切换到‘START_BIT’,同时重置计数器和数据寄存器。

在‘start_bit’状态下,通过计数器进行延迟,等待计数器进行延迟,等待起始位结束,然后将状态位切换到data_bits

在‘data_bits’状态下,通过计数器位逐位接收数据,并将存储在数据寄存器‘serial_data’中。当接收完所有数据后,应该切换到parity_bit位

然后根据parity_bit数据校验位的是否需要,进行逻辑处理

在stop位置等待结束后,切换☞IDLE空闲状态,并将发送状态的‘uart_tx’设置为停止位。

下列给出具体实现代码:

发送端uart_tx实现原理:发送思路原理:我们可以通过定义一个计数器,来记录每次发送所需要的的时间,然后用一个状态机来记录发送的状态。

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 03/10/2024 08:46:28 PM
  7. // Design Name:
  8. // Module Name: uart_tx
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module uart_tx
  22. #( //搜素一下 这里为什么要加井号才能成功
  23. parameter CLK_FRE=50, //默认时钟频率为50Mhz
  24. parameter DATA_WIDTH=8, //有效数据位,缺省为8
  25. parameter PARITY_TYPE=0, //校验类型,1为奇校验,0为偶校验,缺省为偶校验
  26. parameter PARITY_ON=0, //校验位,1为有校验位,0为无校验位,缺省为0
  27. parameter BAUD_RATE=9600 //波特率,缺省为9600
  28. )
  29. (
  30. input i_clk_sys,//系统时钟
  31. input i_rst_n,//全局异步复位
  32. input[DATA_WIDTH-1:0] i_data_tx,//传输数据输入
  33. input i_data_valid,//传输数据有效
  34. output reg o_uart_tx//UART输出
  35. );
  36. //状态机定义
  37. reg[2:0] r_current_state;//当前状态
  38. reg[2:0] r_next_state;//次态
  39. localparam STATE_IDLE=3'b000; //空闲状态
  40. localparam STATE_START=3'b001; //开始状态
  41. localparam STATE_DATA=3'b011; //数据发送状态
  42. localparam STATE_PARITY=3'b100; //数据校验计算和发送
  43. localparam STATE_END=3'b101; //结束状态
  44. localparam CYCLE=CLK_FRE*1000000/BAUD_RATE; //波特率计数周期
  45. reg baud_valid;//波特计数有效位
  46. reg[15:0] baud_cnt; //波特率计数器
  47. reg baud_pulse; //波特率采样脉冲
  48. reg[3:0] r_tx_cnt; //接收数据位计数
  49. //波特率计数器
  50. always @(posedge i_clk_sys or negedge i_rst_n )
  51. begin
  52. if(!i_rst_n) //如果是低电平 则成立
  53. baud_cnt<=16'h0000;
  54. else if(!baud_valid)
  55. baud_cnt<=16'h0000;
  56. else if(baud_cnt==CYCLE-1)
  57. baud_cnt<=16'h0000;
  58. else
  59. baud_cnt=baud_cnt+1;
  60. end
  61. //波特采样脉冲
  62. always @(posedge i_clk_sys or negedge i_rst_n )
  63. begin
  64. if(!i_rst_n)
  65. baud_pulse<=1'b0;
  66. else if(baud_cnt==CYCLE/2-1)
  67. baud_pulse<=1'b1;
  68. else if(baud_valid&&baud_cnt==16'h0000)
  69. r_current_state<= r_next_state;
  70. end
  71. //状态机的次态定义
  72. always @(*)
  73. begin
  74. case(r_current_state)
  75. STATE_IDLE: r_next_state<= STATE_START;
  76. STATE_START: r_next_state<=STATE_DATA;
  77. STATE_DATA:
  78. if(r_tx_cnt==DATA_WIDTH)
  79. begin
  80. if(PARITY_ON==0)
  81. r_next_state<=STATE_END;
  82. else
  83. r_next_state<=STATE_PARITY;
  84. end
  85. else
  86. begin
  87. r_next_state<=STATE_DATA;
  88. end
  89. STATE_PARITY:r_next_state<=STATE_END;
  90. STATE_END:r_next_state<=STATE_IDLE;
  91. default: ;
  92. endcase
  93. end
  94. reg [DATA_WIDTH-1:0] r_data_tx;
  95. reg r_parity_check;
  96. //状态机的输出逻辑
  97. //状态机的输出逻辑根据当前状态执行相应的操作,如发送开始位、数据位、校验位和结束位
  98. always @(posedge i_clk_sys or negedge i_rst_n )
  99. begin
  100. if(!i_rst_n)
  101. begin
  102. baud_valid<=1'b0;
  103. r_data_tx<='d0;
  104. o_uart_tx<=1'b1;
  105. r_tx_cnt<=4'd0;
  106. r_parity_check<=1'b0;
  107. end
  108. else
  109. case(r_current_state)
  110. STATE_IDLE:begin
  111. o_uart_tx<=1'b1;
  112. r_tx_cnt<=4'd0;
  113. r_parity_check<=4'b0;
  114. if(i_data_valid)
  115. begin
  116. baud_valid<=1'b1;
  117. r_data_tx<= i_data_tx;
  118. end
  119. end
  120. STATE_START:begin
  121. if(baud_pulse)
  122. o_uart_tx<=1'b0;
  123. end
  124. STATE_DATA:begin
  125. if(baud_pulse)
  126. begin
  127. r_tx_cnt<=r_tx_cnt+1'b1; //这行代码将r_tx_cnt(数据发送计数器)的值增加1
  128. o_uart_tx<= r_data_tx[0];//这行代码将r_data_tx寄存器中的最低位(第0位)输出到o_uart_tx(UART发送输出)。这意味着数据的最低位被发送出去。
  129. r_parity_check<=r_parity_check+r_data_tx[0];
  130. r_data_tx<={1'b0,r_data_tx[DATA_WIDTH-1:1]};
  131. end
  132. end
  133. /*
  134. 总结来说,当状态机处于STATE_DATA状态且baud_pulse为高电平时,模块会发送当前数据位,更新发送计数器,计算校验位,并准备下一个数据位的发送。\
  135. 这个过程会重复进行,直到所有数据位都被发送完毕。
  136. */
  137. STATE_PARITY:begin
  138. if(baud_pulse) //判断是否具有高电平脉冲过来
  139. begin
  140. if(PARITY_TYPE == 1)
  141. o_uart_tx<= r_parity_check;
  142. else
  143. o_uart_tx<= r_parity_check+1'b1;
  144. end
  145. end
  146. STATE_END:begin
  147. if(baud_pulse)
  148. begin
  149. o_uart_tx<= 1'b1;
  150. baud_valid<=1'b0;
  151. end
  152. end
  153. default:;
  154. endcase
  155. end
  156. endmodule

下面是数据接收端的verilog代码实现,在串口通信时,一定要实现两边的波特率一致,这样才能够同步接收和发送,本次串口通信设置是baud=9600,表是1秒钟可以发送9600个数据位。

(程序中添加了奇偶校验,但是校验不会进行,校验原则:

  • 奇校验(Odd Parity):在数据位中加上一个额外的校验位,使得整个传输的数据(包括校验位)中1的总数为奇数。如果数据位中1的数量已经是奇数,则校验位设为0,以保持总数为奇数;如果是偶数,则校验位设为1。接收端检查接收到的数据中1的总数是否为奇数,如果是,则认为数据传输正确。
  • 偶校验(Even Parity):与奇校验相反,偶校验要求加上的校验位保证数据中1的总数为偶数。如果数据位中1的数量是偶数,则校验位设为0;如果是奇数,则校验位设为1。接收端同样通过检查1的总数是否为偶数来判断数据是否正确。

接收端rx代码:

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 03/13/2024 08:22:34 AM
  7. // Design Name:
  8. // Module Name: uart_rx
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module uart_rx
  22. #(
  23. parameter CLK_FRE=50,//时钟频率,默认为50Mhz
  24. parameter DATA_WIDTH=8,//有效数据位,缺省为8
  25. parameter PARITY_ON=0,//校验位,1为有校验位,0为无校验位,缺省为0
  26. parameter PARITY_TYPE=0,//校验类型,1为奇校验,0为偶校验,缺省为偶校验
  27. parameter BAUD_RATE=9600//波特率,缺省为9600,每秒传输的位数
  28. )//输入输出端口设置
  29. (input i_clk_sys,//系统时钟脉冲
  30. input i_rst_n,//全局异步复位,低电平有效
  31. input i_uart_rx,//uart输入
  32. output reg[DATA_WIDTH-1:0] o_uart_rx,//uart接收数据
  33. output reg o_ld_parity,//校验位校验LED,高电平 位为校验正确
  34. output reg o_rx_done, //数据接收完成标志
  35. output reg o_uart_data
  36. );
  37. /*
  38. UART是异步输入,最好是同步到FPGA内部的时钟域
  39. 可以省略,在异步时钟电路中,保持时钟同步是一个好习惯
  40. */
  41. reg sync_uart_rx; //同步接受数据端,用于同步输入的UART信号,以避免时钟域之间的问题。
  42. always@(posedge i_clk_sys or negedge i_rst_n )
  43. begin
  44. if(!i_rst_n)
  45. sync_uart_rx<=1'b1;
  46. else
  47. sync_uart_rx<=i_uart_rx;
  48. end
  49. /*
  50. 连续采样五个接收路电平来判断rx是否有信号传来
  51. 用五个采样信号来作为判断标准可以有效排除毛刺噪声带来的误判
  52. */
  53. //接受信号检测
  54. reg[4:0] r_flag_rcv_start;
  55. wire w_rcv_start;
  56. always@(posedge i_clk_sys or negedge i_rst_n)
  57. begin
  58. if(!i_rst_n)
  59. r_flag_rcv_start<=5'b11111;
  60. else
  61. r_flag_rcv_start<={r_flag_rcv_start[3:0],sync_uart_rx};
  62. end
  63. //状态机定义
  64. reg[2:0]r_current_state; //当前状态
  65. reg[2:0]r_next_state; //次态
  66. localparam STATE_IDLE=3'b000; //空闲状态
  67. localparam STATE_START=3'b001; //开始状态
  68. localparam STATE_DATA=3'b011; //数据接收状态
  69. localparam STATE_PARITY=3'b000; //空闲状态
  70. localparam STATE_END=3'b101; //结束状态
  71. localparam CYCLE=CLK_FRE*1000000/BAUD_RATE; //ji计算波特率周期 即单个时长
  72. reg baud_valid; //波特率有效位
  73. reg[15:0]baud_cnt;//波特率计数器
  74. reg baud_pulse;//波特率采样脉冲
  75. reg[3:0] r_rcv_cnt;//接收数据位计数
  76. //波特率计数器
  77. always @(posedge i_clk_sys or negedge i_rst_n )
  78. begin
  79. if(!i_rst_n)
  80. baud_cnt<=16'h0000;
  81. else if (!baud_valid)
  82. baud_cnt<=16'h0000;
  83. else if(baud_cnt==CYCLE-1)
  84. baud_cnt<=16'h0000;
  85. else
  86. baud_cnt<=baud_cnt+1'b1;
  87. end
  88. //波特采样脉冲
  89. always @(posedge i_clk_sys or negedge i_rst_n )
  90. begin
  91. if(!i_rst_n)
  92. baud_pulse<=1'b0;
  93. else if(baud_cnt==CYCLE/2-1)
  94. baud_pulse<=1'b1;
  95. else
  96. baud_pulse<=1'b1;
  97. end
  98. //状态机状态变化定义
  99. always @(posedge i_clk_sys or negedge i_rst_n )
  100. begin
  101. if(!i_rst_n) //低电平输入
  102. r_current_state<=STATE_IDLE;
  103. else if(!baud_valid)
  104. r_current_state<=STATE_IDLE;
  105. else if(baud_valid&&baud_cnt==16'h0000)
  106. r_current_state<=r_next_state;
  107. end
  108. //状态机次态定义
  109. always @(*) //。在这个语句中,@(*) 表示该 always 块对敏感列表中的所有信号都敏感。换句话说,当敏感列表中的任何一个信号发生变化时,always 块都会被执行。
  110. begin
  111. case(r_current_state)
  112. STATE_IDLE :r_next_state<=STATE_START;
  113. STATE_START:r_next_state<=STATE_DATA;
  114. STATE_DATA:
  115. if(r_rcv_cnt==DATA_WIDTH)
  116. begin
  117. if(PARITY_ON==0)
  118. r_next_state<=STATE_END;
  119. else
  120. r_next_state<=STATE_PARITY;//校验位开启时进
  121. end
  122. else
  123. begin
  124. r_next_state<=STATE_DATA;
  125. end
  126. STATE_PARITY:r_next_state<=STATE_END;
  127. STATE_END:r_next_state<=STATE_IDLE; //STATE_IDLE 即是空闲位
  128. default:;
  129. endcase
  130. end
  131. reg[DATA_WIDTH-1:0] r_data_rcv; //声明一个8位寄存器
  132. reg r_parity_check; //奇偶校验位寄存器 存储结果
  133. //状态机输出逻辑
  134. always @(posedge i_clk_sys or negedge i_rst_n)
  135. begin
  136. if(!i_rst_n)
  137. begin
  138. baud_valid<=1'b0;
  139. r_data_rcv<='d0;
  140. r_rcv_cnt<=4'd0;
  141. r_parity_check<=1'b0;
  142. o_uart_data<='d0;
  143. baud_pulse<=1'b0;
  144. o_rx_done<=1'b0;
  145. end
  146. else
  147. case(r_current_state)
  148. STATE_IDLE:begin
  149. //闲置状态下 对寄存器进行复位
  150. r_rcv_cnt<=4'd0;
  151. r_data_rcv<='d0;
  152. r_parity_check<=1'b0;
  153. o_rx_done<=1'b0;
  154. //连续检测到低电平,则认为UART传输过来数据,拉高baud_valid。低电平作为数据开始位
  155. if(r_flag_rcv_start==5'b00000)
  156. baud_valid<=1'b1;
  157. end
  158. STATE_START:begin
  159. if(baud_pulse && sync_uart_rx) //波特率采样脉冲到来时
  160. baud_valid<=1'b1;
  161. end
  162. STATE_DATA:begin
  163. if(baud_pulse)
  164. begin
  165. r_data_rcv <={sync_uart_rx,r_data_rcv[DATA_WIDTH-1:1]};//数据移位。将同步串口接收信号(sync_uart_rx)和当前接收到的数据(r_data_rcv)进行移位操作,并将结果赋值给接收数据寄存器(r_data_rcv)。
  166. r_rcv_cnt<=r_rcv_cnt+1'b1;//数据位计数
  167. r_parity_check<=r_parity_check+sync_uart_rx;//校验位做校验
  168. end
  169. end
  170. STATE_PARITY:begin
  171. if(baud_pulse) //如果是高电平
  172. begin
  173. //校验检测,正确则0_ld_parity拉高,则可输出给led检测,如果闪烁则表示有错误数据
  174. if(r_parity_check+sync_uart_rx==PARITY_TYPE)
  175. o_ld_parity<=1'b1;
  176. else
  177. o_ld_parity<=1'b0;
  178. end
  179. else
  180. o_ld_parity<=o_ld_parity;
  181. end
  182. STATE_END:begin
  183. if(baud_pulse)
  184. begin
  185. //没有校验位或校验位正确时才输出数据,否则直接丢弃数据
  186. if(PARITY_ON==0||o_ld_parity)
  187. begin
  188. o_uart_data<= r_data_rcv;
  189. o_rx_done<=1'b1;
  190. end
  191. end
  192. else
  193. begin
  194. o_rx_done<=1'b0;
  195. end
  196. if(baud_cnt==16'h0000)
  197. baud_valid<=1'b0;
  198. end
  199. default:;
  200. endcase
  201. end
  202. endmodule

如上串口通信的发送端程序和接收端程序均已完美。但是还需要做一个顶层程序来调动发送端和接收端。即是给uart_tx发送端和uart_rx 接收端初始化相关寄存器变量。整个模块的功能用来接收来自UART的输入信号,并将其传输给UART模块输出。同时使用校验位检验LED来指示检验是否正确。

如下代码:

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 03/13/2024 11:31:45 AM
  7. // Design Name:
  8. // Module Name: uart_loop
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module uart_loop(
  22. input i_clk_sys,
  23. input i_rst_n,
  24. input i_uart_rx,
  25. output o_uart_tx,
  26. output o_ld_parity
  27. );
  28. localparam DATA_WIDTH = 8;
  29. localparam BAUD_RATE = 9600;
  30. localparam PARITY_ON = 1;
  31. localparam PARITY_TYPE = 1;
  32. wire w_rx_done;
  33. wire[DATA_WIDTH-1 : 0] w_data;
  34. uart_rx
  35. #(
  36. .CLK_FRE(50), //时钟频率,默认时钟频率为50MHz
  37. .DATA_WIDTH(DATA_WIDTH), //有效数据位,缺省为8
  38. .PARITY_ON(PARITY_ON), //校验位,1为有校验位,0为无校验位,缺省为0
  39. .PARITY_TYPE(PARITY_TYPE), //校验类型,1为奇校验,0为偶校验,缺省为偶校验
  40. .BAUD_RATE(BAUD_RATE) //波特率,缺省为9600
  41. ) u_uart_rx
  42. (
  43. .i_clk_sys(i_clk_sys), //系统时钟
  44. .i_rst_n(i_rst_n), //全局异步复位,低电平有效
  45. .i_uart_rx(i_uart_rx), //UART输入
  46. .o_uart_data(w_data), //UART接收数据
  47. .o_ld_parity(o_ld_parity), //校验位检验LED,高电平位为校验正确
  48. .o_rx_done(w_rx_done) //UART数据接收完成标志
  49. );
  50. uart_tx
  51. #(
  52. .CLK_FRE(50), //时钟频率,默认时钟频率为50MHz
  53. .DATA_WIDTH(DATA_WIDTH), //有效数据位,缺省为8
  54. .PARITY_ON(PARITY_ON), //校验位,1为有校验位,0为无校验位,缺省为0
  55. .PARITY_TYPE(PARITY_TYPE), //校验类型,1为奇校验,0为偶校验,缺省为偶校验
  56. .BAUD_RATE(BAUD_RATE) //波特率,缺省为9600
  57. ) u_uart_tx
  58. ( .i_clk_sys(i_clk_sys), //系统时钟
  59. .i_rst_n(i_rst_n), //全局异步复位
  60. .i_data_tx(w_data), //传输数据输入
  61. .i_data_valid(w_rx_done), //传输数据有效
  62. .o_uart_tx(o_uart_tx) //UART输出
  63. );
  64. endmodule

下面是电路仿真实现:

该模块的输入包括:

  • i_clk_sys:系统时钟信号。
  • i_rst_n:全局异步复位信号,低电平有效。
  • i_uart_rx:UART输入信号。

该模块的输出包括:

  • o_uart_tx:UART输出信号。
  • o_ld_parity:校验位检验LED,高电平表示校验正确

下面在波形仿真模块,先定义一些寄存器变量,和线型变量,然后分别调用发送模块和数据接收模块。并且初始化全局复位和时钟信号。

  1. `timescale 1ns / 1ps
  2. //
  3. // Company: 南京信息工程大学
  4. // Engineer: 王彪
  5. //
  6. // Create Date: 03/13/2024 07:43:29 PM
  7. // Design Name: 同步串口通信
  8. // Module Name: uart_loop_tb
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module uart_loop_tb(
  22. );
  23. reg clk_sys;
  24. reg rst_n;
  25. reg uart_in;
  26. wire uart_out;
  27. wire parity;
  28. uart_loop u_uart_loop(
  29. .i_clk_sys(clk_sys),
  30. .i_rst_n(rst_n),
  31. .i_uart_rx(uart_in),
  32. .o_uart_tx(uart_out),
  33. .o_ld_parity(parity)
  34. );
  35. initial begin
  36. clk_sys = 1'b0;
  37. rst_n = 1'b0;
  38. uart_in = 1'b1;
  39. end
  40. always #10 clk_sys = ~clk_sys;
  41. localparam ELEMENT_TIME = 104160;
  42. reg [7:0] DATA = 8'hAC;
  43. initial begin
  44. #100 rst_n = 1'b1;
  45. #20000;
  46. // #并且可以使用#来进行时间等待。
  47. uart_in = 1'b0;//uart_in = 1'b0; 将UART输入信号uart_in设置为低电平,模拟开始位的发送。
  48. #ELEMENT_TIME
  49. uart_in = DATA[0];
  50. #ELEMENT_TIME
  51. uart_in = DATA[1];
  52. #ELEMENT_TIME
  53. uart_in = DATA[2];
  54. #ELEMENT_TIME
  55. uart_in = DATA[3];
  56. #ELEMENT_TIME
  57. uart_in = DATA[4];
  58. #ELEMENT_TIME
  59. uart_in = DATA[5];
  60. #ELEMENT_TIME
  61. uart_in = DATA[6];
  62. #ELEMENT_TIME
  63. uart_in = DATA[7];
  64. #ELEMENT_TIME
  65. uart_in = 1'b1;
  66. #ELEMENT_TIME
  67. uart_in = 1'b1;
  68. end
  69. //总结来说,这个测试模块通过模拟发送一个包含8位数据的UART数据帧,包括开始位、数据位、校验位(如果有的话)和停止位。
  70. //ELEMENT_TIME参数用于控制每个位的时间间隔,以确保数据按照正确的时序发送。这个测试模块可以用来检查UART接收模块是否能够正确地接收和处理发送的数据。
  71. endmodule

下面进行全局行为仿真,发送的数8为16进制ac

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/473398
推荐阅读
相关标签
  

闽ICP备14008679号