串口系列知识分享:
(1)串口通信实现-串口发送
(2)串口通信发送多字节数据
(3)串口通信实现-串口接收
(4)UART 通信-使用VIO进行板级验证
(5)串口接收-控制LED闪烁
(6)使用串口发送实现ACX720开发板时钟显示
(7)串口发送+RAM+VGA传图
前言
在上一篇博客中,主要实现了将单字节的数据,我们其实就是用上一篇博客的模块来实现多字节数据的发送。
提示:以下是本篇文章正文内容,下面案例可供参考
一、需求分析
上一篇文中,单字节的串口发送模块为uart_tx。实现的具体功能为,当send_go为高电平时,将data里的并行数据以串行数据发出,发送完成时 tx_done 产生一个单脉冲。我们需要在上层模块中调用这个模块。所以,需要trans_go启动状态机,状态机内部产身send_go信号,传输一字节数据。发送完成后,uart_tx模块会产生tx_done信号,tx_done信号用来激活状态机的下一个状态,开始发送下一个数据,再次产生一个send_go脉冲,送入data数据,依次送完5字节数据,当最后一个字节发送完成成,最后一个状态5在tx_done下返回第一个状态,并产生五字节发送完成信号,trans_down.回到第一个状态后,等待发送下一个四十位,五字节数据的trans_go。状态转移图如下。
————————————————
二、设计文件和testbench文件
1.设计文件
代码如下(示例):
module uart_tx_data2(
Clk,
Reset_n,
Data40,
Trans_Go,
uart_tx,
Trans_Done
);
input Clk;
input Reset_n;
input [39:0]Data40;
input Trans_Go;
output uart_tx;
output reg Trans_Done;
reg [7:0]Data;
reg Send_Go;
wire Tx_done;
//例化uart_byte_tx模块 (见上一篇博客)
uart_byte_tx uart_byte_tx(
.Clk(Clk),
.Reset_n(Reset_n),
.Data(Data),
.Send_Go(Send_Go),
.Baud_set(4),
.uart_tx(uart_tx),
.Tx_done(Tx_done)
);
reg [2:0]state;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)begin
state <= 0;
Data <= 0;
Send_Go <= 0;
Trans_Done <= 0;
end
else begin
case(state)
0:
begin
Trans_Done <= 0;
if(Trans_Go)begin
Data <= Data40[7:0];
Send_Go <= 1;
state <= 1;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 0;
end
end
1:
begin
if(Tx_done)begin
Data <= Data40[15:8];
Send_Go <= 1;
state <= 2;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 1;
end
end
2:
begin
if(Tx_done)begin
Data <= Data40[23:16];
Send_Go <= 1;
state <= 3;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 2;
end
end
3:
begin
if(Tx_done)begin
Data <= Data40[31:24];
Send_Go <= 1;
state <= 4;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 3;
end
end
4:
begin
if(Tx_done)begin
Data <= Data40[39:32];
Send_Go <= 1;
state <= 5;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 4;
end
end
5:
begin
if(Tx_done)begin
Send_Go <= 0;
Trans_Done <= 1;
state <= 0;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 5;
end
end
default:
begin
Data <= Data;
Send_Go <= 0;
state <= 0;
end
endcase
end
endmodule
2.testbench文件
代码如下(示例):
`timescale 1ns / 1ps
module uart_tx_data_tb();
reg Clk;
reg Reset_n;
reg [39:0]Data40;
reg Trans_Go;
wire uart_tx;
uart_tx_data2 uart_tx_data(
Clk,
Reset_n,
Data40,
Trans_Go,
uart_tx,
Trans_Done
);
initial Clk = 1;
always #10 Clk = ~Clk;
initial begin
Reset_n =0;
Data40 = 0;
Trans_Go = 0;
#201;
Reset_n = 1;
#200;
Data40 = 40'h123456789a;
Trans_Go = 1;
#20;
Trans_Go = 0;
@(posedge Trans_Done);
#200000;
Data40 = 40'ha987654321;
Trans_Go = 1;
#20;
Trans_Go = 0;
@(posedge Trans_Done);
#200000;
$stop;
end
endmodule
【注】:至此多字节数据发送就完结,下面将展示通过时间控制多字节发送过程。
二、时间控制多字节发送
1.设计文件
设置每1s发送一个数据,每次数据发完将数据加1,即第一秒发送40’d0,第二秒发送40’d1,… 依次发送。
module uart_tx_data2_test(
Clk,
Reset_n,
uart_tx,
);
input Clk;
input Reset_n;
output uart_tx;
reg Trans_Go;
reg [39:0]Data;
wire Trans_Done;
uart_tx_data2 uart_tx_data2(
.Clk(Clk),
.Reset_n(Reset_n),
.Data40(Data),
.Trans_Go(Trans_Go),
.uart_tx(uart_tx),
.Trans_Done(Trans_Done)
);
reg [24:0]counter;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter == 4999999)
counter <= 0;
else
counter <= counter + 1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Trans_Go <= 0;
else if(counter == 0)
Trans_Go <= 1;
else
Trans_Go <= 0;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Data <= 0;
else if(Trans_Done)
Data <= Data + 1'b1;
endmodule
2.TB文件
`timescale 1ns / 1ps
module uart_tx_data2_test_tb();
reg Clk;
reg Reset_n;
wire uart_tx;
uart_tx_data2_test uart_tx_data2_test(
.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;
#50000000;
end
endmodule
3.仿真波形
【附件:】链接:https://pan.baidu.com/s/1lJBfUxSye7jf73wvX0iQJg?pwd=6h8k
提取码:6h8k