RS-232 Transmitter
目录
上篇博文讲到了如何产生波特率?(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)上的完整代码过于复杂,我自己改成简单的形式,并仿真:
-
module ays_transmitter(
-
input clk,
-
input TxD_start,
-
input [7:0] TxD_data,
-
output TxD,
-
output TxD_busy
-
-
);
-
-
reg [3:0] TxD_state = 0;
-
wire TxD_ready = (TxD_state==0);
-
assign TxD_busy = ~TxD_ready;
-
-
-
//Generate Baud Clock
-
wire BitTick;
-
-
BaudGen u_BaudGen(
-
.clk(clk),
-
.enable(TxD_busy), //generate baud clk only when transmiter data
-
.BaudTick(BitTick)
-
);
-
-
reg [7:0] TxD_shift = 0;
-
always @(posedge clk) begin
-
if(TxD_ready & TxD_start)
-
TxD_shift <= TxD_data;
-
else
-
if(TxD_state[3] & BitTick)
-
TxD_shift <= (TxD_shift >> 1);
-
-
case(TxD_state)
-
4'b0000: if(TxD_start) TxD_state <= 4'b0100;
-
4'b0100: if(BitTick) TxD_state <= 4'b1000; // start bit
-
4'b1000: if(BitTick) TxD_state <= 4'b1001; // bit 0
-
4'b1001: if(BitTick) TxD_state <= 4'b1010; // bit 1
-
4'b1010: if(BitTick) TxD_state <= 4'b1011; // bit 2
-
4'b1011: if(BitTick) TxD_state <= 4'b1100; // bit 3
-
4'b1100: if(BitTick) TxD_state <= 4'b1101; // bit 4
-
4'b1101: if(BitTick) TxD_state <= 4'b1110; // bit 5
-
4'b1110: if(BitTick) TxD_state <= 4'b1111; // bit 6
-
4'b1111: if(BitTick) TxD_state <= 4'b0010; // bit 7
-
4'b0010: if(BitTick) TxD_state <= 4'b0011; // stop1
-
4'b0011: if(BitTick) TxD_state <= 4'b0000; // stop2
-
default: if(BitTick) TxD_state <= 4'b0000;
-
endcase
-
end
-
-
-
assign TxD = (TxD_state<4) | (TxD_state[3] & TxD_shift[0]); // put together the start, data and stop bits
-
-
-
-
endmodule
BaudGen模块:
-
module BaudGen(
-
input clk,
-
input enable,
-
output BaudTick
-
);
-
-
parameter ClkFrequency = 25000000; // 25MHz
-
parameter Baud = 115200;
-
parameter Ratio = ClkFrequency/Baud;
-
parameter BaudGeneratorAccWidth = 16;
-
parameter BaudGeneratorInc = (1<<BaudGeneratorAccWidth)/Ratio;
-
-
reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc = 0;
-
always @(posedge clk)
-
if(enable)
-
BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;
-
else
-
BaudGeneratorAcc <= BaudGeneratorInc;
-
assign BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];
-
-
endmodule
测试模块:
-
`timescale 1ns / 1ps
-
//
-
// Create Date: 2019/05/26 16:06:48
-
// Design Name:
-
// Module Name: ays_transmitter_tb
-
//
-
-
-
module ays_transmitter_tb(
-
-
);
-
-
reg clk;
-
reg TxD_start;
-
reg [7:0] TxD_data;
-
wire TxD;
-
wire TxD_busy;
-
-
initial begin
-
clk = 0;
-
forever
-
#20 clk = ~clk;
-
-
end
-
-
initial begin
-
TxD_start = 0;
-
TxD_data = 8'b10010101;
-
#50
-
TxD_start = 1;
-
-
end
-
-
-
ays_transmitter u_ays_transmitter(
-
.clk(clk),
-
.TxD_start(TxD_start),
-
.TxD_data(TxD_data),
-
.TxD(TxD),
-
.TxD_busy(TxD_busy)
-
-
);
-
-
-
endmodule
仿真波形图:
从上图可以看出,每一个波特时钟发送一bit数据:从低到高位发送10101001,之后发送两个结束位1.
下面这幅图是显示下一次发送前的空闲期,TxD_busy为低。之后又进入了下一帧数据的发送。
参考链接:
https://www.fpga4fun.com/SerialInterface3.html
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/90576294
- 点赞
- 收藏
- 关注作者
评论(0)