FPGA串口收發(三):接收數據,再轉發出去
功能:測試串口接收數據,再將數據從串口發出
// 模擬串口信號線,串行接收數據 1101_1000 ,轉換爲並行數據, 並顯示 D8
// 把並行數據 D8 傳給串口輸出模塊,串行輸出數據 1101 1000
時鐘40MHz,波特率115200
1、源文件
uart_rx.v
uart_tx.v
2、仿真文件 testbench
tb_uart_rx_tx.v
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Myminieye
// Engineer: Nill
//
// Create Date:
// Design Name:
// Module Name:
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 測試串口接收數據,再將數據從串口發出
// 模擬串口信號線,串行接收數據 1101_1000 ,轉換爲並行數據, 並顯示 D8
// 把並行數據 D8 傳給串口輸出模塊,串行輸出數據 1101 1000
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define UD #1
module tb_uart_rx_tx();
//==========================================================================
//wire and reg 定義:信號與參數
//==========================================================================
reg sim_clk; //模擬時鐘信號
//reg tx_pulse; // active posedge
reg sim_rst_n;
// input to rx module
reg uart_rx; //串口發送信號線
//output from rx module
wire [7:0] rx_data; //送入串口發送模塊,準備發送的數據
wire rx_finish; //串口接收數據有效,接收完成拉高1個BPS
// input to tx module
reg tx_pulse; // active posedge
reg [7:0] tx_data; //送入串口發送模塊,準備發送的數據
//output from tx module
wire uart_tx; //串口發送信號線
wire tx_busy; //串口發送模塊狀態
//時鐘參數
parameter SYS_CLK_FRE = 40_000_000; //系統頻率40MHz 40_000_000
parameter SYS_CLK_PERIOD = 1_000_000_000/SYS_CLK_FRE; //週期25ns
parameter RST_CYCLE = 5; //復位持續時間,clk時鐘週期數
parameter RST_TIME = RST_CYCLE * SYS_CLK_PERIOD; //復位時間:5個時鐘週期
//波特率參數
parameter BAUD_RATE = 115200; //串口波特率
parameter BAUD_RATE_PERIOD = 1_000_000_000/BAUD_RATE;
//波特率週期,0.104ms = 104us,1/9600 s = 1^9 /9600 ns = 4167 sim_clk
//波特率週期, 1/115200 = 8680 ns = 8.7us = 347 sim_clk
//波特率+時鐘參數
parameter [15:0] BPS_NUM = SYS_CLK_FRE / BAUD_RATE; //時鐘/波特率,用時鐘週期構造波特率週期
// BPS_NUM = 40_000_000/115200 = 347.22 = 16'd347
// 1 bit位寬所需時鐘週期的個數。最長的波特率計數,10417,二進制有14位,取16位
// parameter BPS_4800: 40MHz set 8333 ; 50MHz set 10417
// parameter BPS_9600: 40MHz set 4167 ; 50MHz set 5208
// parameter BPS_115200: 40MHz set 347; 50MHz set 434
//==========================================================================
//模擬:信號的輸入,顯示輸出結果
//==========================================================================
//模擬系統時鐘:40MHz,25ns
always #((SYS_CLK_PERIOD+1)/2-1) sim_clk = ~sim_clk; //延時,電平翻轉
initial begin
//模擬復位信號:拉低一次
#0;
sim_clk = 1'b0;
sim_rst_n = 1'b0; //復位拉低,有效,
uart_rx = 1'b1; //串口線,默認高,起始拉低
//rx_data <= `UD 8'h00; //rx_data 初始化,在 uart_rx中完成
tx_pulse = 1'b0; //觸發發送,高有效,先拉低
tx_data = 8'h00; //數據默認爲0
//#RST_TIME; //延時:保持足夠長時間(至少5個clk)
#BAUD_RATE_PERIOD; //5個clk時間軸太短,仿真改爲1個BPS,更明顯
sim_rst_n = 1'b1; //解除復位
//==========================================================================
//模擬串口接收:串行信號輸入,轉化成並行數據,並顯示
//==========================================================================
uart_rx = 1'b1; //串口發送線,默認拉高
repeat( BPS_NUM*1 ) @(posedge sim_clk); //循環347個時鐘週期,即一個波特率週期
//#BAUD_RATE_PERIOD; //直接延時,一個波特率週期
$display("Initialization complete. BAUD_RATE is %d",BAUD_RATE); //命令行顯示初始化完成,輸出BAUD_RATE
//串口:起始位
uart_rx = 1'b0;
#BAUD_RATE_PERIOD;
//串行數據,一位一位送入接收信號線:***從位0到位7***,依次發送
//測試數據爲8'hD8=8'b1101_1000
uart_rx = 1'b0;
#BAUD_RATE_PERIOD;
uart_rx = 1'b0;
#BAUD_RATE_PERIOD;
uart_rx = 1'b0;
#BAUD_RATE_PERIOD;
uart_rx = 1'b1;
#BAUD_RATE_PERIOD;
uart_rx = 1'b1;
#BAUD_RATE_PERIOD;
uart_rx = 1'b0;
#BAUD_RATE_PERIOD;
uart_rx = 1'b1;
#BAUD_RATE_PERIOD;
uart_rx = 1'b1;
#BAUD_RATE_PERIOD;
$display("The uart_rx 8'hD8 = 8'b1101_1000 has been sent."); //命令行顯示:串口信號線數據已發送
//串口:結束位
uart_rx = 1'b1;
#BAUD_RATE_PERIOD;
$display("The uart_rx has received. rx_data = 8'h%h",rx_data);
//命令行顯示:串口信號線接收已結束,顯示接收到的數據
//==========================================================================
//模擬串口發送:並行數據,串行輸出
//==========================================================================
//***串口接收模塊收到的數據,傳遞給串口輸出模塊***
repeat( BPS_NUM*1 ) @(posedge sim_clk); //循環347個時鐘週期,即一個波特率週期
//#BAUD_RATE_PERIOD; //直接延時,一個波特率週期
//傳遞 第一組數據:8位並行數據,一次性送入串口發送模塊
tx_data = rx_data; //串口接收數據,傳給串口發送
#BAUD_RATE_PERIOD;
//開啓觸發信號:串口發送
//tx_pulse = 1; //用 rx_en 代替 模擬tx_pulse,直接觸發
#BAUD_RATE_PERIOD; //rx_en 串口接收數據有效,接收完成拉高1個BPS
//結束觸發:串口發送
//tx_pulse = 0;
#BAUD_RATE_PERIOD;
repeat( BPS_NUM*9 ) @(posedge sim_clk); //發送數據,等待8個波特率週期
$display("The first tx_data 8'h%h has been sent.",tx_data); //命令行顯示:第1組數據發送完
#BAUD_RATE_PERIOD;
$stop; //結束仿真
end
//==========================================================================
//調用top模塊
//==========================================================================
//串口發送
uart_rx #(
//.CLK_SYS ( SYS_CLK_FRE), //系統時鐘
.BPS_NUM ( BPS_NUM ) // 時鐘/波特率,1 bit位寬所需時鐘週期的個數
)
u_uart_rx(
.clk ( sim_clk ),// input clk,
//.rst_n ( sim_rst_n ),// input
.uart_rx ( uart_rx ),// input reg 串口接收信號線
.rx_data ( rx_data ),// output 接收到的數據
.rx_finish( rx_finish)// output 串口接收數據有效,接收完成拉高1個BPS
//.rx_end ( rx_end ) // output //接收到停止位,拉高1個clk,沒啥用
);
//串口發送
uart_tx #(
//.CLK_SYS ( SYS_CLK_FRE), //系統時鐘
.BPS_NUM ( BPS_NUM ) // 時鐘/波特率,用時鐘週期構造波特率週期
)
u_uart_tx(
.clk ( sim_clk ),// input clk,
.tx_data ( tx_data ),// input [7:0] tx_data,
.tx_pulse ( rx_finish),// input 外部輸入,開始產生數據->開啓串口發送狀態
.uart_tx ( uart_tx ),// output reg uart_tx,
.tx_busy ( tx_busy ), // output 輸出,串口接收忙狀態
.tx_finish( tx_finish) // output //串口發送數據結束標誌,8位數據發完,拉高一個BPS
);
endmodule
3、仿真結果
ModelSim波形
命令行顯示
增加 tx_finish 和 rx_finish