RS-232 Transmitter

举报
李锐博恩 发表于 2021/07/15 03:45:25 2021/07/15
【摘要】 目录 串行化数据 Verilog描述并仿真 上篇博文讲到了如何产生波特率?(RS232 波特率时钟产生方法?) 下面的内容是构建一个异步发送器: 我们正在构建一个具有固定参数的“异步发送器”:8个数据位,2个停止位,无奇偶校验。 它的工作方式如下: 发送器在FPGA内部获取一个8位数据并将其串行化(从“TxD_start”信号置位时开始)。 在发生传输时断...

目录

串行化数据

Verilog描述并仿真


上篇博文讲到了如何产生波特率?(RS232 波特率时钟产生方法?

下面的内容是构建一个异步发送器:

我们正在构建一个具有固定参数的“异步发送器”:8个数据位,2个停止位,无奇偶校验。

它的工作方式如下:

发送器在FPGA内部获取一个8位数据并将其串行化(从“TxD_start”信号置位时开始)。
在发生传输时断言“忙”信号(在此期间忽略“TxD_start”信号)。

串行化数据


要查看起始位,8个数据位和停止位,状态机似乎是合适的。

reg [3:0] state;

// the state machine starts when "TxD_start" is asserted, but advances when "BaudTick" is asserted (115200 times a second)
always @(posedge clk)
case(state)
  4'b0000: if(TxD_start) state <= 4'b0100;
  4'b0100: if(BaudTick) state <= 4'b1000; // start
  4'b1000: if(BaudTick) state <= 4'b1001; // bit 0
  4'b1001: if(BaudTick) state <= 4'b1010; // bit 1
  4'b1010: if(BaudTick) state <= 4'b1011; // bit 2
  4'b1011: if(BaudTick) state <= 4'b1100; // bit 3
  4'b1100: if(BaudTick) state <= 4'b1101; // bit 4
  4'b1101: if(BaudTick) state <= 4'b1110; // bit 5
  4'b1110: if(BaudTick) state <= 4'b1111; // bit 6
  4'b1111: if(BaudTick) state <= 4'b0001; // bit 7
  4'b0001: if(BaudTick) state <= 4'b0010; // stop1
  4'b0010: if(BaudTick) state <= 4'b0000; // stop2
  default: if(BaudTick) state <= 4'b0000;
endcase

现在,我们只需要生成“TxD”输出。

reg muxbit;

always @(state[2:0])
case(state[2:0])
  0: muxbit <= TxD_data[0];
  1: muxbit <= TxD_data[1];
  2: muxbit <= TxD_data[2];
  3: muxbit <= TxD_data[3];
  4: muxbit <= TxD_data[4];
  5: muxbit <= TxD_data[5];
  6: muxbit <= TxD_data[6];
  7: muxbit <= TxD_data[7];
endcase

// combine start, data, and stop bits together
assign TxD = (state<4) | (state[3] & muxbit);


Verilog描述并仿真

Verilog描述:

由于参考链接(https://www.fpga4fun.com/SerialInterface3.html)上的完整代码过于复杂,我自己改成简单的形式,并仿真:


  
  1. module ays_transmitter(
  2. input clk,
  3. input TxD_start,
  4. input [7:0] TxD_data,
  5. output TxD,
  6. output TxD_busy
  7. );
  8. reg [3:0] TxD_state = 0;
  9. wire TxD_ready = (TxD_state==0);
  10. assign TxD_busy = ~TxD_ready;
  11. //Generate Baud Clock
  12. wire BitTick;
  13. BaudGen u_BaudGen(
  14. .clk(clk),
  15. .enable(TxD_busy), //generate baud clk only when transmiter data
  16. .BaudTick(BitTick)
  17. );
  18. reg [7:0] TxD_shift = 0;
  19. always @(posedge clk) begin
  20. if(TxD_ready & TxD_start)
  21. TxD_shift <= TxD_data;
  22. else
  23. if(TxD_state[3] & BitTick)
  24. TxD_shift <= (TxD_shift >> 1);
  25. case(TxD_state)
  26. 4'b0000: if(TxD_start) TxD_state <= 4'b0100;
  27. 4'b0100: if(BitTick) TxD_state <= 4'b1000; // start bit
  28. 4'b1000: if(BitTick) TxD_state <= 4'b1001; // bit 0
  29. 4'b1001: if(BitTick) TxD_state <= 4'b1010; // bit 1
  30. 4'b1010: if(BitTick) TxD_state <= 4'b1011; // bit 2
  31. 4'b1011: if(BitTick) TxD_state <= 4'b1100; // bit 3
  32. 4'b1100: if(BitTick) TxD_state <= 4'b1101; // bit 4
  33. 4'b1101: if(BitTick) TxD_state <= 4'b1110; // bit 5
  34. 4'b1110: if(BitTick) TxD_state <= 4'b1111; // bit 6
  35. 4'b1111: if(BitTick) TxD_state <= 4'b0010; // bit 7
  36. 4'b0010: if(BitTick) TxD_state <= 4'b0011; // stop1
  37. 4'b0011: if(BitTick) TxD_state <= 4'b0000; // stop2
  38. default: if(BitTick) TxD_state <= 4'b0000;
  39. endcase
  40. end
  41. assign TxD = (TxD_state<4) | (TxD_state[3] & TxD_shift[0]); // put together the start, data and stop bits
  42. endmodule

BaudGen模块:


  
  1. module BaudGen(
  2. input clk,
  3. input enable,
  4. output BaudTick
  5. );
  6. parameter ClkFrequency = 25000000; // 25MHz
  7. parameter Baud = 115200;
  8. parameter Ratio = ClkFrequency/Baud;
  9. parameter BaudGeneratorAccWidth = 16;
  10. parameter BaudGeneratorInc = (1<<BaudGeneratorAccWidth)/Ratio;
  11. reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc = 0;
  12. always @(posedge clk)
  13. if(enable)
  14. BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;
  15. else
  16. BaudGeneratorAcc <= BaudGeneratorInc;
  17. assign BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];
  18. endmodule

测试模块:


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Create Date: 2019/05/26 16:06:48
  4. // Design Name:
  5. // Module Name: ays_transmitter_tb
  6. //
  7. module ays_transmitter_tb(
  8. );
  9. reg clk;
  10. reg TxD_start;
  11. reg [7:0] TxD_data;
  12. wire TxD;
  13. wire TxD_busy;
  14. initial begin
  15. clk = 0;
  16. forever
  17. #20 clk = ~clk;
  18. end
  19. initial begin
  20. TxD_start = 0;
  21. TxD_data = 8'b10010101;
  22. #50
  23. TxD_start = 1;
  24. end
  25. ays_transmitter u_ays_transmitter(
  26. .clk(clk),
  27. .TxD_start(TxD_start),
  28. .TxD_data(TxD_data),
  29. .TxD(TxD),
  30. .TxD_busy(TxD_busy)
  31. );
  32. endmodule

仿真波形图:

从上图可以看出,每一个波特时钟发送一bit数据:从低到高位发送10101001,之后发送两个结束位1.

下面这幅图是显示下一次发送前的空闲期,TxD_busy为低。之后又进入了下一帧数据的发送。

 

 

参考链接:

https://www.fpga4fun.com/SerialInterface3.html

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/90576294

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。