序
本项目采用Altera的FPGA,串口多字节接收,并解码以及采用ModelSim进行仿真。串口接收程序源自正点原子的例程。
程序基本框架
程序分为两个部分,单字节接收部分和多字节接收及解码部分,其中单字节接收部分参考资料比较多,收到单字节数据并给出完成标志位;多字节接收在此基础上进行若干个字节的接收,并给出标志位,通过解码模块对数据进行解码。
程序源码
采用Quartus II开发环境,频率50MHz,波特率 115200,8位数据位,1位停止位。
由于手头核心板比较奇怪,是高电平复位,因此程序中复位信号是上升沿,修改一下即可。
module uart_top(
input sys_clk, //系统时钟
input sys_rst_n, //系统复位,低电平有效
input uart_rxd, //UART接收端口
output reg [ 7:0] uart_data,
output reg uart_done,
output reg uart_get, //采样点
output reg [7:0] pack_cnt, //字节计数
output reg pack_ing, //接收过程标志位
output reg pack_done, //帧接收完成标志位
output reg [7:0] pack_num, //接收到的字节数
output reg recv_done, //接收完一帧数据的接收和解码
output reg [7:0] dataA, //解码后数据
output reg [15:0] dataB, //解码后数据
output reg [15:0] dataC //解码后数据
);
localparam DATA_NUM = 8;
integer j;
reg [7:0] pack_data [DATA_NUM-1:0]; //接收的数据
//parameter define
parameter CLK_FREQ = 50_000_000; //系统时钟频率
parameter UART_BPS = 115200; //串口波特率
localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率
localparam TimeOut = BPS_CNT*DATA_NUM*10*2;//超时时间
//起始信号下降沿捕捉
wire start_flag;
reg uart_rxd_d0;
reg uart_rxd_d1;
reg [15:0] clk_cnt; //系统时钟计数器
reg [ 3:0] rx_cnt; //接收数据计数器
reg rx_flag; //接收过程标志信号
reg [ 7:0] rxdata; //接收数据寄存器
//接收信号完成标志位上升沿
wire rxdone_flag;
reg uart_done_d0;
reg uart_done_d1;
//包数据接收完成
wire packdone_flag;
reg pack_done_d0;
reg pack_done_d1;
//*****************************************************
//** main code
//*****************************************************
//捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
//对UART接收端口的数据延迟两个时钟周期
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
uart_rxd_d0 <= 1'b0;
uart_rxd_d1 <= 1'b0;
end
else begin
uart_rxd_d0 <= uart_rxd;
uart_rxd_d1 <= uart_rxd_d0;
end
end
//当脉冲信号start_flag到达时,进入接收过程
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n)
rx_flag <= 1'b0;
else begin
if(start_flag) //检测到起始位
rx_flag <= 1'b1; //进入接收过程,标志位rx_flag拉高
else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
rx_flag <= 1'b0; //计数到停止位中间时,停止接收过程
else
rx_flag <= rx_flag;
end
end
//进入接收过程后,启动系统时钟计数器与接收数据计数器
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
clk_cnt <= 16'd0;
rx_cnt <= 4'd0;
end
else if ( rx_flag ) begin //处于接收过程
if (clk_cnt < BPS_CNT - 1) begin
clk_cnt <= clk_cnt + 1'b1;
rx_cnt <= rx_cnt;
end
else begin
clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零
rx_cnt <= rx_cnt + 1'b1; //此时接收数据计数器加1
end
end
else begin //接收过程结束,计数器清零
clk_cnt <= 16'd0;
rx_cnt <= 4'd0;
end
end
//根据接收数据计数器来寄存uart接收端口数据
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
rxdata <= 8'd0;
uart_get<=1'b0;
end
else if(rx_flag) //系统处于接收过程
if (clk_cnt == BPS_CNT/2) begin //判断系统时钟计数器计数到数据位中间
case ( rx_cnt )
4'd1 : rxdata[0] <= uart_rxd_d1; //寄存数据位最低位
4'd2 : rxdata[1] <= uart_rxd_d1;
4'd3 : rxdata[2] <= uart_rxd_d1;
4'd4 : rxdata[3] <= uart_rxd_d1;
4'd5 : rxdata[4] <= uart_rxd_d1;
4'd6 : rxdata[5] <= uart_rxd_d1;
4'd7 : rxdata[6] <= uart_rxd_d1;
4'd8 : rxdata[7] <= uart_rxd_d1; //寄存数据位最高位
default:;
endcase
uart_get<=1'b1;
end
else begin
rxdata <= rxdata;
uart_get<=1'b0;
end
else begin
rxdata <= 8'd0;
uart_get<=1'b0;
end
end
//数据接收完毕后给出标志信号并寄存输出接收到的数据
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
else if(rx_cnt == 4'd9) begin //接收数据计数器计数到停止位时
uart_data <= rxdata; //寄存输出接收到的数据
uart_done <= 1'b1; //并将接收完成标志位拉高
end
else begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
end
//---单字节接收程序,uart_done接收完成标志位会持续半个波特率周期,捕捉上升沿可以计数,高电平状态,接收数据有效
//==============================================接收多个字节,添加的模块====================================================//
//捕获接收完成标志位的上升沿,得到一个时钟周期的脉冲信号
assign rxdone_flag = uart_done_d0 & (~uart_done_d1);
//对UART完成标志的数据延迟两个时钟周期
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
uart_done_d0 <= 1'b0;
uart_done_d1 <= 1'b0;
end
else begin
uart_done_d0 <= uart_done;
uart_done_d1 <= uart_done_d0;
end
end
//接收到的数据存入数组中,并计数
always @(posedge sys_clk or posedge sys_rst_n) begin //接收到数据
if (sys_rst_n) begin
pack_cnt <=8'd0;
pack_num <=8'd0;
pack_done<=1'b0;
pack_ing <=1'b0;
for (j=0;j<DATA_NUM;j=j+1)
pack_data[j] <= 8'd0;
end
else if(rxdone_flag) begin //接收完成标志位的上升沿,延迟了两个时钟周期
if (pack_cnt < DATA_NUM-1) begin //处于接收过程中
for (j=0;j<DATA_NUM;j=j+1) begin
if(j==pack_cnt)
pack_data[pack_cnt] <= uart_data;//寄存输出接收到的数据
else
pack_data[j] <= pack_data[j];
end
pack_cnt <= pack_cnt + 1'b1;
pack_num <= 8'd0;
pack_done<=1'b0;
pack_ing <=1'b1;
end
else begin //接收完成---最后一个字节的接收
for (j=0;j<DATA_NUM;j=j+1) begin
if(j==pack_cnt)
pack_data[pack_cnt] <= uart_data;//寄存输出接收到的数据
else
pack_data[j] <= pack_data[j];
end
pack_num <= pack_cnt + 1'b1; //加上最后一个字节
pack_cnt <= 8'd0; //此时接收数据计数器归零,只有接收完成时才清零
pack_done<=1'b1; //输出帧接收完成标志位,只存在一个周期
pack_ing <=1'b0;
end
end
else begin
pack_cnt <=pack_cnt;
pack_ing <=pack_ing;//保持
pack_num <=pack_num;
pack_done<=1'b0;
for (j=0;j<DATA_NUM;j=j+1)
pack_data[j] <= pack_data[j];
end
end
//------------解码-------------------------//
//捕获接收完成标志位的上升沿,得到一个时钟周期的脉冲信号
assign packdone_flag = pack_done_d0 & (~pack_done_d1);
//对UART完成标志的数据延迟两个时钟周期
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
pack_done_d0 <= 1'b0;
pack_done_d1 <= 1'b0;
end
else begin
pack_done_d0 <= pack_done;
pack_done_d1 <= pack_done_d0;
end
end
always @(posedge sys_clk or posedge sys_rst_n) begin
if (sys_rst_n) begin
dataA <= 8'd0;
dataB <= 16'd0;
dataC <=16'd0;
recv_done <=1'b0;
end
else if(packdone_flag) begin //数据接收完成,进行解码
if(pack_num==DATA_NUM && pack_data[0]==8'h55 && pack_data[6]==8'h0d && pack_data[7]==8'h0a ) begin //判断数据正误
dataA <=pack_data[1];
dataB <= {pack_data[3],pack_data[2]};
dataC <= {pack_data[5],pack_data[4]};
recv_done <=1'b1;
end
else begin //数据错误
dataA <= 8'd1;
dataB <= 16'd0;
dataC <=16'd0;
recv_done <=1'b0;
end
end
else begin //数据保持到下一个周期,标志位保持一个周期
dataA <= dataA;
dataB <= dataB;
dataC <=dataC;
recv_done <=1'b0;
end
end
endmodule
ModelSim仿真
仿真发送两包数据,每包数据八个字节,数据格式为 55 12 13 14 15 16 0d 0a
`timescale 1ns / 1ps
// Description: 测试串口
// Dependencies:
module uart_top_vlg_tst();
//==========================================================================
//wire and reg 定义:信号与参数
//==========================================================================
// input to module
reg sim_clk; //模拟时钟信号
//reg tx_pulse; // active posedge
reg sim_rst_n;
reg uart_rxd; //串口发送信号线
//output from module
wire [7:0] rx_data; //送入串口发送模块,准备发送的数据
wire rx_en; //串口接收数据有效,接收完成拉高1个BPS
wire rx_get;
wire [7:0] pack_cnt;
wire pack_done;
wire pack_ing;
wire [7:0] pack_num;
wire recv_done;
wire [7:0] dataA;
wire [15:0] dataB;
wire [15:0] dataC;
//时钟参数
parameter SYS_CLK_FRE = 50_000_000; //系统频率50MHz 40_000_000
parameter SYS_CLK_PERIOD = 1_000_000_000/SYS_CLK_FRE; //周期20ns
//波特率参数
parameter BAUD_RATE = 230400; //串口波特率
parameter BAUD_RATE_PERIOD = 1_000_000_000/BAUD_RATE;
//==========================================================================
//模拟时钟信号
//==========================================================================
//模拟系统时钟:50MHz,20ns
always #((SYS_CLK_PERIOD)/2) sim_clk = ~sim_clk; //延时,电平翻转
//模拟系统时钟:40MHz,25ns
// always #((SYS_CLK_PERIOD+1)/2-1) sim_clk = ~sim_clk; //延时,电平翻转
initial begin
//模拟复位信号:一次,低电平5个clk
#0;
sim_clk = 1'b0;
sim_rst_n = 1'b1; //复位
#BAUD_RATE_PERIOD;
sim_rst_n = 1'b0; //解除复位
//==========================================================================
//模拟串口接收:串行信号输入,转化成并行数据,并显示
//==========================================================================
uart_rxd = 1'b1; //串口发送线,默认拉高
#BAUD_RATE_PERIOD; //直接延时,一个波特率周期
$display("Initialization complete. BAUD_RATE is %d",BAUD_RATE); //命令行显示初始化完成,输出BPS_NUM
//一帧数据
$display("The first byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h55=8'b0101_0101
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h55=8'b0101_0101 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
//一帧数据
$display("The second byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h12=8'b0001_0010
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h12=8'b0001_0010 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
//一帧数据
$display("The third byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h13=8'b0001_0011
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h13=8'b0001_0011 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 4 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h14=8'b0001_0100
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h14=8'b0001_0100 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 5 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h15=8'b0001_0101
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h15=8'b0001_0101 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 6 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h16=8'b0001_0110
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h16=8'b0001_0110 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 7 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h0d=8'b0000_1101
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h0d=8'b0000_1101 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 8 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h0a=8'b0000_1010
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h0a=8'b0000_1010 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
//------------------第二包数据------------------------//
$display("The second package...");
//一帧数据
$display("The first byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h55=8'b0101_0101
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h55=8'b0101_0101 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
//一帧数据
$display("The second byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h32=8'b0011_0010
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h32=8'b0011_0010 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
//一帧数据
$display("The third byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h33=8'b0011_0011
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h33=8'b0011_0011 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 4 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h34=8'b0011_0100
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h34=8'b0011_0100 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 5 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h35=8'b0001_0101
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h35=8'b0011_0101 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 6 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h36=8'b0001_0110
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h36=8'b0011_0110 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 7 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h0d=8'b0000_1101
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h0d=8'b0000_1101 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
$display("The 8 byte...");
//发送数据----起始位
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
//测试数据为8'h0a=8'b0000_1010
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b1; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
uart_rxd = 1'b0; #BAUD_RATE_PERIOD;
$display("The uart_rxd 8'h0a=8'b0000_1010 has been sent."); //命令行显示:串口信号线数据已发送
//发送数据----停止位
uart_rxd = 1'b1;
#(BAUD_RATE_PERIOD/3);//为了显示
$display("The uart_rxd has received. rx_data = 8'h%h",rx_data);
#(BAUD_RATE_PERIOD*2/3);
//命令行显示:串口信号线接收已结束,显示接收到的数据
#BAUD_RATE_PERIOD;
#BAUD_RATE_PERIOD;
$stop; //结束仿真
end
//==========================================================================
//调用top模块
//==========================================================================
//串口接收
uart_top #(
.CLK_FREQ (SYS_CLK_FRE), //系统时钟
.UART_BPS ( BAUD_RATE ) // 时钟/波特率,1 bit位宽所需时钟周期的个数
)
u_uart_top(
.sys_clk (sim_clk),
.sys_rst_n (sim_rst_n),
.uart_done (rx_en),
.uart_rxd (uart_rxd),
.uart_data (rx_data),
.uart_get (rx_get),
.pack_cnt (pack_cnt),
.pack_done (pack_done),
.pack_ing (pack_ing),
.pack_num (pack_num),
.recv_done (recv_done),
.dataA (dataA),
.dataB (dataB),
.dataC (dataC)
);
endmodule
致谢参考:
https://blog.csdn.net/nomil9/article/details/106763694?spm=1001.2014.3001.5501