1. 串口发送数据任务
- 任务要求:
使用上一节课设计的串口发送模块,设计一个数据发送器,每10ms以115200的波特率发送一个比特,每次发送的数据比前一个数据大1(计数器)
1.1 设计思路
- 模块化设计,使用上一节课设计好的发送模块
1.2 设计开始
- 设计Uart_Byte_Tx(单字节发送)模块
选择使用以下变量
Clk
Reset_N
Uart_Tx
cnt
10ms个数计数器
- 代码和仿真代码如下
代码:
module Uart_Tx(
Clk,
Reset_N,
Uart_Tx
);
input Clk;
input Reset_N;
output Uart_Tx;
reg [7:0]Data;
reg Send_En;
wire Tx_Done;
Uart_Byte_Tx Uart_Byte_Tx(
.Clk(Clk),
.Reset_N(Reset_N),
.Data(Data),
.Send_En(Send_En),
.Baud_Set(3'd4),
.Uart_Tx(Uart_Tx),
.Tx_Done(Tx_Done)
);
reg [18:0]cnt;
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)
cnt <= 0;
else if(cnt == 499999)
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)
Send_En <= 0;
else if(cnt == 1)
Send_En <= 1'b1;
else if(Tx_Done)
Send_En <= 0;
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)
Data <= 0;
else if(Tx_Done)
Data <= Data + 1'b1;
else
Data <= Data;
endmodule
仿真代码:
`timescale 1ns / 1ns
module Uart_Tx_tb;
reg Clk;
reg Reset_N;
wire Uart_tx;
Uart_Tx Uart_Tx(
.Clk(Clk),
.Reset_N(Reset_N),
.Uart_Tx(Uart_tx)
);
initial Clk = 1;
always #10 Clk = ~Clk;
initial begin
Reset_N = 0;
#201;
Reset_N = 1;
#20000000;
$stop;
end
endmodule
1.3 仿真结果
仿真结果如图所示:
-
遇到的问题
- 仅能正常传输第一个码字
Send_En
在传输完成后一直为低电平Tx_Done
传输完成后一直为高电平
-
问题分析
- 通过查看
Uart_Tx
代码可知,Send_En
的值受Tx_Done
控制。在Uart_Byte_Tx
代码中,码字命中case(11)
情况后使得Tx_Done = 1
,导致Send_En
无法使能。Send_En
一直为低使得计数器Div_cnt
和Bps_cnt
无法增加,进而无法命中情况case(1)
。而case(1)
又是使得Tx_Done = 0
的唯一可能。
- 解决方案
- 为了使得
Tx_Done = 0
情况出现,加入情况case(0)
,在命中0
时让Tx_Done = 0
。更改部分的Uart_Byte_Tx
代码如下:
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)begin
Uart_Tx <= 1'b1;
Tx_Done <= 0;
end
else
case(Bps_cnt)
0: Tx_Done <= 0;
1: Uart_Tx <= 0;
2: Uart_Tx <= Data[0];
3: Uart_Tx <= Data[1];
4: Uart_Tx <= Data[2];
5: Uart_Tx <= Data[3];
6: Uart_Tx <= Data[4];
7: Uart_Tx <= Data[5];
8: Uart_Tx <= Data[6];
9: Uart_Tx <= Data[7];
10: Uart_Tx <= 1'b1;
11: begin
Tx_Done <= 1'b1;
Uart_Tx <= 1'b1;
end
default: Uart_Tx <= 1'b1;
endcase
仿真结果:
和
1.4 修改后结果分析
-
遇到的问题
- 在1.3的第一张仿真图中,可以看到第二个比特可以正常传输了
- 传输的第二个码字却是3
-
问题分析
- 通过观察1.3的第二张仿真图可以看到,短时间内
Data
增加了两次,接着分析这两次增加为什么产生。 - 通过查看
Uart_Tx
代码可知,Data
的值在Tx_Done == 1
时自增。图中可以看到Tx_Done
维持了三个高电平,使得增加了三次。因此考虑Tx_Done = 1
维持一个高电平。
- 通过观察1.3的第二张仿真图可以看到,短时间内
-
解决方案
-
维持一个高电平的解决方案。观察1.3的第二张仿真图可知,信号
Bps_Clk
维持了一个高电平,考虑从此处下手。 -
更改部分的
Uart_Byte_Tx
代码如下:
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)begin
Uart_Tx <= 1'b1;
Tx_Done <= 0;
end
else
case(Bps_cnt)
1: Uart_Tx <= 0;
2: Uart_Tx <= Data[0];
3: Uart_Tx <= Data[1];
4: Uart_Tx <= Data[2];
5: Uart_Tx <= Data[3];
6: Uart_Tx <= Data[4];
7: Uart_Tx <= Data[5];
8: Uart_Tx <= Data[6];
9: Uart_Tx <= Data[7];
10: Uart_Tx <= 1'b1;
11: Uart_Tx <= 1'b1;
default: Uart_Tx <= 1'b1;
endcase
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)
Tx_Done <= 0;
else if((Bps_cnt == 10) && Bps_Clk)
Tx_Done <= 1'b1;
else
Tx_Done <= 0;
1.5 仿真结果
- 可以看到数据传输基本正常