当前位置:   article > 正文

基于FPGA实现uart串口模块(Verilog)--------发送模块及整合_uart控制模块,发送模块,接收模块带fifo的联合仿真

uart控制模块,发送模块,接收模块带fifo的联合仿真

基于FPGA实现uart串口模块(Verilog)--------发送模块及整合

当接收模块接收到数据后,需要重新发送形成回环验证模块正确性。思路和结束模块有一点点的小差异。接收模块最终输出的是一个并行的八位数据,所以只有在最后输出保证输出结果正确就可以,而发送模块必须按照波特率时钟发送每一位的数据。具体代码实现如下

代码实现

  1. module uart_tx(
  2. //-----------input
  3. clk,rst_n,pi_data,pi_flag,
  4. //-----------output
  5. tx_data
  6. );
  7. input clk;
  8. input rst_n;
  9. input [7:0] pi_data;
  10. input pi_flag;
  11. output tx_data;
  12. parameter idle = 2'd0,
  13. start = 2'd1,
  14. work = 2'd2,
  15. stop = 2'd3;
  16. //------------------------------
  17. localparam baud_cnt_end = 5207 ;
  18. localparam baud_cnt_m = (baud_cnt_end + 1) / 2 - 1;
  19. //------------------------------
  20. //------------------------------
  21. reg pi_flag1;
  22. reg pi_flag2;
  23. reg tx_flag;
  24. reg [12:0] baud_cnt;
  25. reg [3:0] bit_cnt;
  26. reg tx_data;
  27. reg [1:0] current_state;
  28. reg [1:0] next_state;
  29. always@(posedge clk )
  30. begin
  31. pi_flag1 <= pi_flag;
  32. pi_flag2 <= pi_flag1;
  33. end
  34. //------------------------------
  35. //第一个进程,同步时序always块,形式固定
  36. always@(posedge clk or negedge rst_n)
  37. begin
  38. if(!rst_n)
  39. current_state <= idle;
  40. else
  41. current_state <= next_state;
  42. end
  43. //第二个always,组合逻辑模块,描述状态迁移条件判断
  44. always@(*)
  45. begin
  46. case(current_state)
  47. idle:
  48. begin
  49. tx_flag = 1'b0;
  50. begin
  51. if(pi_flag2)
  52. next_state = start;
  53. else
  54. next_state = idle;
  55. end
  56. end
  57. start:
  58. begin
  59. tx_flag = 1'b1;
  60. begin
  61. if(bit_cnt == 4'd1)
  62. next_state = work;
  63. else
  64. next_state = start;
  65. end
  66. end
  67. work:
  68. begin
  69. tx_flag = 1'b1;
  70. begin
  71. if(bit_cnt == 4'd9)
  72. next_state = stop;
  73. else
  74. next_state = work;
  75. end
  76. end
  77. stop:
  78. begin
  79. tx_flag = 1'b1;
  80. begin
  81. if(bit_cnt == 4'd10)
  82. next_state = idle;
  83. else
  84. next_state = stop;
  85. end
  86. end
  87. default:
  88. begin
  89. next_state = idle;
  90. end
  91. endcase
  92. end
  93. //第三个进程,描述输出,同步时序always块
  94. //reg [3:0] bit_cnt;
  95. always@(posedge clk or negedge rst_n)
  96. begin
  97. if(!rst_n)
  98. bit_cnt <= 4'd0;
  99. else
  100. if(!tx_flag)
  101. bit_cnt <= 4'd0;
  102. else
  103. if(baud_cnt == baud_cnt_end)
  104. bit_cnt <= bit_cnt + 1'b1;
  105. end
  106. //reg [12:0] baud_cnt;
  107. always@(posedge clk or negedge rst_n)
  108. begin
  109. if(!rst_n)
  110. baud_cnt <= 13'd0;
  111. else
  112. if(baud_cnt == baud_cnt_end)
  113. baud_cnt <= 13'd0;
  114. else
  115. if(tx_flag)
  116. baud_cnt <= baud_cnt + 1'b1;
  117. else
  118. baud_cnt <= 13'd0;
  119. end
  120. reg [7:0] pi_data_r;
  121. always@(posedge clk or negedge rst_n)
  122. begin
  123. if(!rst_n)
  124. pi_data_r <= 8'd0;
  125. else
  126. if(pi_flag)
  127. pi_data_r <= pi_data;
  128. else
  129. pi_data_r <= pi_data_r;
  130. end
  131. //define tx_data
  132. always@(posedge clk or negedge rst_n)
  133. begin
  134. if(!rst_n)
  135. tx_data <= 1'b1;
  136. else
  137. if(tx_flag)
  138. case(bit_cnt)
  139. 4'd0 : tx_data <= 1'b0 ;
  140. 4'd1 : tx_data <= pi_data_r[0] ;
  141. 4'd2 : tx_data <= pi_data_r[1] ;
  142. 4'd3 : tx_data <= pi_data_r[2] ;
  143. 4'd4 : tx_data <= pi_data_r[3] ;
  144. 4'd5 : tx_data <= pi_data_r[4] ;
  145. 4'd6 : tx_data <= pi_data_r[5] ;
  146. 4'd7 : tx_data <= pi_data_r[6] ;
  147. 4'd8 : tx_data <= pi_data_r[7] ;
  148. 4'd9 : tx_data <= 1'b1 ;
  149. default:;
  150. endcase
  151. else
  152. tx_data <= 1'b1;
  153. end
  154. endmodule

顶层文件(模块整合)

  1. module top_uart(
  2. input clk ,
  3. input rst_n ,
  4. input rx_data ,
  5. output tx_data
  6. );
  7. wire [7:0] data;
  8. wire flag;
  9. uart_tx A(
  10. .clk (clk ),
  11. .rst_n (rst_n ),
  12. .pi_data (data ),
  13. .pi_flag (flag ),
  14. .tx_data (tx_data)
  15. );
  16. uart_rx B(
  17. .clk (clk ),
  18. .rst_n (rst_n ),
  19. .rx_data (rx_data),
  20. .po_data (data ),
  21. .po_flag (flag )
  22. );
  23. endmodule

仿真代码

  1. module tb_fsm;
  2. // Inputs
  3. reg clk;
  4. reg rst_n;
  5. reg rx_data;
  6. // Outputs
  7. wire tx_data;
  8. // Instantiate the Unit Under Test (UUT)
  9. top_uart uut (
  10. .clk(clk),
  11. .rst_n(rst_n),
  12. .rx_data(rx_data),
  13. .tx_data(tx_data)
  14. );
  15. always #10 clk = ~clk;
  16. initial begin
  17. // Initialize Inputs
  18. clk = 0;
  19. rst_n = 0;
  20. rx_data = 1;
  21. // Wait 100 ns for global reset to finish
  22. #100;
  23. rst_n = 1;
  24. #104140;
  25. rx_data = 1;
  26. #104140;
  27. rx_data = 1;
  28. #104140;
  29. rx_data = 1;
  30. #104140;
  31. rx_data = 1;
  32. #104140;
  33. rx_data = 1;
  34. #104140;
  35. rx_data = 0;//start
  36. #104140;
  37. rx_data = 0;//1
  38. #104140;
  39. rx_data = 1;//2
  40. #104140;
  41. rx_data = 0;//3
  42. #104140;
  43. rx_data = 1;//4
  44. #104140;
  45. rx_data = 0;//5
  46. #104140;
  47. rx_data = 1;//6
  48. #104140;
  49. rx_data = 0;//7
  50. #104140;
  51. rx_data = 1;//8
  52. #104140;
  53. rx_data = 1;
  54. #104140;
  55. rx_data = 1;
  56. #104140;
  57. rx_data = 1;
  58. #104140;
  59. rx_data = 1;
  60. #104140;
  61. rx_data = 1;
  62. #104140;
  63. rx_data = 0;
  64. #104140;
  65. rx_data = 1;//1
  66. #104140;
  67. rx_data = 0;
  68. #104140;
  69. rx_data = 1;
  70. #104140;
  71. rx_data = 0;//4
  72. #104140;
  73. rx_data = 1;
  74. #104140;
  75. rx_data = 0;
  76. #104140;
  77. rx_data = 1;
  78. #104140;
  79. rx_data = 0;//8
  80. #104140;
  81. rx_data = 1;
  82. #104140;
  83. rx_data = 1;
  84. #104140;
  85. rx_data = 1;
  86. // Add stimulus here
  87. end
  88. endmodule

反思小结

对于uart,发送和接收应该是人机交互的一个方式,通过发送的字符控制内部等等其他东西。对于模块不理解的可以回头看看仿真图,对图中的各个时序进行理解。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号