串口通信系列2——发送模块
上篇文章介绍了一下UART接收模块,这篇我们谈一谈发送模块。
发送模块将需要传输的8位数据以字符帧格式发送出去。那我们就开门见山,发送模块由哪些模块组成?
由上图可知,波特率定时模块在发送模块中依然扮演着非常重要的角色。
波特率定时模块:当bps_start信号为低电平时,波特率定时模块不工作。当bps_start信号为高电平时,波特率定时模块使能工作,然后定时产生一个高脉冲bps_clk给发送模块。
发送控制模块:当tx_en_sig信号使能时,发送模块同时把bps_start信号置高电平,使能波特率定时模块。发送控制模块按波特率定时模块产生的定时将tx_data数据,有时间规律的发送给rs232_tx,当数据发送完毕,发送控制模块产生一个脉冲信号tx_done_sig。
我们先来看一看bps_module.v:
module bps_module( clk,rst_n, bps_start, bps_clk ); input clk,rst_n; input bps_start; output bps_clk; `define BPS_PARA 5207 `define BPS_PARA_2 2603 reg[12:0] cnt; always@(posedge clk or negedge rst_n) begin if(!rst_n) cnt <= 13'd0; else if(cnt == `BPS_PARA) cnt <= 13'd0; else if(bps_start) cnt <= cnt + 1'b1; else cnt <= 13'd0; end assign bps_clk = (cnt == `BPS_PARA_2)? 1'b1 : 1'b0; endmodule
其实我们可以发现发送波特率定时模块与接收模块的波特率定时模块完全一样。接收模块中波特率定时模块在每一帧中数据位的中间进行“定时”,而发送模块应该在每一帧中数据位的起始进行“定时”,怎么会发送和接收模块中的波特率定时模块完全一样了?
这里很多人会搞不清楚,那我再问一个问题,波特率两个定时之间相差了多少个计数(时间)?答案显而易见是5028(0~5027),第一次定时波特率模块计2604个数(0~2603)产生一个脉冲,到第二次定时中间相差5208个数,这不就是一个数据位所占的时间。
发送控制模块tx_control_module.v
module tx_control_module(
clk,rst_n,
tx_en_sig,tx_data,bps_clk,
bps_start,rs232_tx, tx_done_sig
);
input clk,rst_n;
input tx_en_sig, bps_clk;
input [7:0]tx_data;
output bps_start,tx_done_sig, rs232_tx;
reg [3:0]i;
reg bps_start_r;
reg tx_done_sig_r;
reg rs232_tx_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
i <= 1'd0;
bps_start_r <= 1'b0;
tx_done_sig_r <= 1'b0;
rs232_tx_r <= 1'b1;
end
else if(tx_en_sig)
case(i)
4'd0:begin
i <= i+1'b1;
bps_start_r <= 1'b1;
end
4'd1:if(bps_clk)
begin
i <= i+1'b1;
rs232_tx_r <= 1'b0;
end
4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9:
if(bps_clk)
begin
i <= i+1'b1;
rs232_tx_r <= tx_data[i-2];
end
4'd10:if(bps_clk)
begin
i <= i+1'b1;
rs232_tx_r <= 1'b1;
end
4'd11:if(bps_clk)
begin
i <= i+1'b1;
rs232_tx_r <= 1'b1;
end
4'd12:if(bps_clk)
begin
i <= i+1'b1;
bps_start_r <= 1'b0;
tx_done_sig_r <= 1'b1;
end
4'd13: begin
i <= 4'd0;
tx_done_sig_r <= 1'b0;
end
default: ;
endcase
end
assign bps_start = bps_start_r;
assign tx_done_sig = tx_done_sig_r;
assign rs232_tx = rs232_tx_r;
endmodule
串口发送模块(顶层模块)tx_module.v
module tx_module(
clk,rst_n,
tx_en_sig,tx_data,
rs232_tx,tx_done_sig
);
input clk,rst_n;
input tx_en_sig;
input [7:0]tx_data;
output tx_done_sig, rs232_tx;
wire bps_clk;
wire bps_start;
bps_module U1(
.clk (clk ),
.rst_n (rst_n ),
.bps_start (bps_start), // form U2
.bps_clk (bps_clk ) // to U2
);
tx_control_module U2(
.clk (clk ),
.rst_n (rst_n ),
.tx_en_sig (tx_en_sig ),
.tx_data (tx_data ),
.bps_clk (bps_clk ),
.bps_start (bps_start ),
.rs232_tx (rs232_tx ),
.tx_done_sig (tx_done_sig)
);
endmodule
testbench代码tx_module_tb.v
`timescale 1ns / 1ps
module tx_module_tb;
reg clk;
reg rst_n;
reg tx_en_sig;
reg [7:0]tx_data;
wire rs232_tx;
wire tx_done_sig;
tx_module i_tx_module(
.clk (clk ),
.rst_n (rst_n ),
.tx_en_sig (tx_en_sig ),
.tx_data (tx_data ),
.rs232_tx (rs232_tx ),
.tx_done_sig(tx_done_sig)
);
initial begin clk = 0; forever #10 clk = ~clk; end
initial begin
rst_n = 0;tx_en_sig = 0;
#1000;
rst_n = 1;
tx_en_sig = 1;
#1000;
tx_data = 8'b10101010;
#1000000000;
$stop;
end
endmodule
modelsim仿真波形:
此次实验的重点在于理解波特率定时模块与tx_control_module.v红色字体部分,modelsim仿真由于跑的时间较长,只是贴出大概波形,有兴趣的朋友可以跑一跑modelsim分析一下具体的信号,以便更好的理解。
未完待续……
(本文章转载自博客,作者wiliamzhou)