一、模块设计
在实际工业应用中,现场往往有非常强的电磁干扰,只采样一次就作为该数据的电平状态是不可靠的,很有可能恰好采集到被干扰的信号而导致结果出错。
1、基本原理:采样
2、技巧:一位数据采多次,统计其电平高低情况,出现次数多的就是该位数据的值。
采样八次,若出现高电平的次数为0、1、2、3则该为数据为低电平,
若出现高电平的次数为 4、5、6、7,则该为数据为高电平。
3、起始位检测:通过边沿检测电路
因此,将每位数据分为16份,采每位数据的5—11段,并根据高低电平出现的次数判断该位数据的值。
设计输入
//在实际工业应用中,现场往往有非常强的电磁干扰,只采样一次就作为该数据的电平状态是不可靠的,很有可能恰好采集到被干扰的信号而导致结果出错;
//因此,将每位数据分为16份,采每位数据的5—11段,并根据高低电平出现的次数判断该位数据的值。
module uart_byte_rx(
Clk ,
Reset_n ,
Baud_Set ,//波特率选择信号,需要和数据发送波特率一致
uart_rx ,//输入串行数据
Data ,//将接收到的数据传送出去,并行输出
Rx_Done //接收完成信号
);
input Clk ;
input Reset_n ;
input [2:0]Baud_Set ;
input uart_rx ;
output reg [7:0]Data ;
output reg Rx_Done ;
//定义两个寄存器,实现边缘检测电路
reg [1:0]uart_rx_r; //先将数据进行存储,两个D触发器
always@(posedge Clk)begin
uart_rx_r[0] <= uart_rx;
uart_rx_r[1] <= uart_rx_r[0];
end
//检测边沿
wire pedge_uart_rx; //上升沿
// assign pedge_uart_rx = ((uart_rx_r[1] = 0)&&(uart_rx_r[0] == 1));
assign pedge_uart_rx = (uart_rx_r == 2'b01);
wire nedge_uart_rx; //下降沿
// assign pedge_uart_rx = ((uart_rx_r[1] = 1)&&(uart_rx_r[0] == 0));
assign nedge_uart_rx = (uart_rx_r == 2'b10);
//波特率设置,在采样时要把每位数据发送的时间分为16段进行采样
reg [8:0] Bps_DR;
always@(*)
case(Baud_Set)
0:Bps_DR = 1000000000/9600/16/20 - 1;
1:Bps_DR = 1000000000/19200/16/20 - 1;
2:Bps_DR = 1000000000/38400/16/20 - 1;
3:Bps_DR = 1000000000/57600/16/20 - 1;
4:Bps_DR = 1000000000/115200/16/20 - 1;
default:Bps_DR = 1000000000/9600/16/20 - 1;
endcase
//产生bps_clk,每一小段,取最中间的值
wire bps_clk_16x;
reg [8:0]div_cnt;
assign bps_clk_16x = (div_cnt == Bps_DR / 2);
//需要一个分频计数器
reg RX_EN; //数据接收的时候,RX_EN处于高电平
reg [2:0]sta_bit;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
RX_EN <= 0;
else if(nedge_uart_rx) //当检测到下降沿,即下一位为发送起始位,开始接收数据
RX_EN <= 1;
else if(Rx_Done || (sta_bit >= 4)) // 当Rx_Done拉高,或者检测到发送起始位并不是真正的起始位
RX_EN <= 0;
//reg [8:0]div_cnt; 分频计数器,计数一个波特率
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
div_cnt <= 0;
else if(RX_EN)begin
if(div_cnt == Bps_DR)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 0;
//计数器,传送一八位数据需要十个时间段,每个时间段分16小段,计数16*10 = 160 次,
//每当bps_clk_16x到来一次,计数器加一
reg [7:0]bps_cnt;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
bps_cnt <= 0;
else if(RX_EN)begin
if(bps_clk_16x)begin
if(bps_cnt == 160)
bps_cnt <= 0;
else
bps_cnt <= bps_cnt + 1'b1;
end
else
bps_cnt <= bps_cnt;
end
else
bps_cnt <= 0;
//接收数据,每位数据采样八次,将八次采样值进行累加,判断累加后的值r_data;
//若值为0-3 则该位数据为0,若值为4-7 则该位数据为1。
//reg 位宽width name number
reg[2:0]r_data[7:0]; //表示定义了8个3位的寄存器r_data;定义八个是为了和要接收的八位数据对应,后边再分别定义起始位和结束位
// r_data[0][1] 表示第0个r_data中的第一位数据
//reg [2:0]sta_bit;
reg [2:0]sto_bit;
//接收数据
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)begin
sta_bit <= 0;
sto_bit <= 0;
r_data[0] <= 0;
r_data[1] <= 0;
r_data[2] <= 0;
r_data[3] <= 0;
r_data[4] <= 0;
r_data[5] <= 0;
r_data[6] <= 0;
r_data[7] <= 0;
end
else if(bps_clk_16x)begin
case(bps_cnt)
0:begin
sta_bit <= 0;
sto_bit <= 0;
r_data[0] <= 0;
r_data[1] <= 0;
r_data[2] <= 0;
r_data[3] <= 0;
r_data[4] <= 0;
r_data[5] <= 0;
r_data[6] <= 0;
r_data[7] <= 0;
end
5,6,7,8,9,10,11:sta_bit <= sta_bit + uart_rx;
21,22,23,24,25,26,27:r_data[0] <= r_data[0] + uart_rx;
37,38,39,40,41,42,43:r_data[1] <= r_data[1] + uart_rx;
53,54,55,56,57,58,59:r_data[2] <= r_data[2] + uart_rx;
69,70,71,72,73,74,75:r_data[3] <= r_data[3] + uart_rx;
85,86,87,88,89,90,91:r_data[4] <= r_data[4] + uart_rx;
101,102,103,104,105,106,107:r_data[5] <= r_data[5] + uart_rx;
117,118,119,120,121,122,123:r_data[6] <= r_data[6] + uart_rx;
133,134,135,136,137,138,139:r_data[7] <= r_data[7] + uart_rx;
149,150,151,152,153,154,155:sto_bit <= sto_bit + uart_rx;
default:;
endcase
end
//输出结果,给到Data
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Data <= 0;
else if((bps_cnt == 159 ))begin
Data[0] <= (r_data[0] >= 4)? 1'b1:1'b0;
Data[1] <= (r_data[1] >= 4)? 1'b1:1'b0;
Data[2] <= (r_data[2] >= 4)? 1'b1:1'b0;
Data[3] <= (r_data[3] >= 4)? 1'b1:1'b0;
Data[4] <= (r_data[4] >= 4)? 1'b1:1'b0;
Data[5] <= (r_data[5] >= 4)? 1'b1:1'b0;
Data[6] <= (r_data[6] >= 4)? 1'b1:1'b0;
Data[7] <= (r_data[7] >= 4)? 1'b1:1'b0;
end
// 0:3'b000;
// 1:3'b001;
// 2:3'b010;
// 3:3'b011;
// 4:3'b100;
// 5:3'b101;
// 6:3'b110;
// 7:3'b110;
//0-3 的第二位都为0,4-7的第二位都为1
// always@(posedge Clk or negedge Reset_n)
// if(!Reset_n)
// Data <= 0;
// else if((bps_cnt == 159 ))begin
// Data[0] <= r_data[0][2] ; //等价于 Data[0] <= (r_data[0] >= 4)? 1'b1:1'b0;
// Data[1] <= r_data[1][2] ; //将r_data[1] 第二位的值赋给Data[1]
// Data[2] <= r_data[2][2] ;
// Data[3] <= r_data[3][2] ;
// Data[4] <= r_data[4][2] ;
// Data[5] <= r_data[5][2] ;
// Data[6] <= r_data[6][2] ;
// Data[7] <= r_data[7][2] ;
// end
//给Rx_Done值
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Rx_Done <= 0;
else if((div_cnt == Bps_DR) && (bps_cnt == 160 )) //脉冲到来,并且计数到最后一位数159时
Rx_Done <= 1;
else
Rx_Done <= 0;
endmodule
功能仿真代码
`timescale 1ns / 1ps
module uart_byte_rx_tb();
reg Clk ;
reg Reset_n ;
wire [2:0]Baud_Set ;
reg uart_rx ;
wire [7:0]Data ;
wire Rx_Done ;
assign Baud_Set = 4;
uart_byte_rx uart_byte_rx (
Clk ,
Reset_n ,
Baud_Set ,
uart_rx ,
Data ,
Rx_Done
);
initial Clk = 1;
always #10 Clk = ~Clk;
initial begin
Reset_n = 0 ;
uart_rx = 1 ;
#201;
Reset_n = 1;
#200;
uart_tx_byte (8'h5a) ;
#90000;
uart_tx_byte (8'ha5) ;
#90000;
uart_tx_byte (8'h86) ;
#90000;
$stop;
end
task uart_tx_byte;
input [7:0]tx_data;
begin
uart_rx = 1;
#20;
uart_rx = 0; //起始位
#8680; //115200的波特率发送数据,每位保持时间为8680ns
uart_rx = tx_data[0];
#8680;
uart_rx = tx_data[1];
#8680;
uart_rx = tx_data[2];
#8680;
uart_rx = tx_data[3];
#8680;
uart_rx = tx_data[4];
#8680;
uart_rx = tx_data[5];
#8680;
uart_rx = tx_data[6];
#8680;
uart_rx = tx_data[7];
#8680;
uart_rx = 1; //结束位
#8680;
end
endtask
endmodule
功能仿真结果
二、项目实例 使用串口控制LED的工作状态
使用串口发送指令到FPGA开发板,控制led灯:
让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
使用五个比特数据,分别对应Time值和Ctrl值。制定一个发送协议,使用移位寄存器实现该功能。
设计输入
顶层模块
`timescale 1ns / 1ps
module uart_rx_ctrl_led(
Clk ,
Reset_n ,
uart_rx ,
LED
);
input Clk ;
input Reset_n ;
input uart_rx ;
output LED ;
wire [7:0]ctrl;
wire [31:0]time_set;
wire [7:0]rx_data;
wire rx_done;
wire Led;
counter_led_4 counter_led_4(
.Clk (Clk) ,
.Reset_n (Reset_n) ,
.Ctrl (ctrl) ,
.Time (time_set) ,
.Led (Led)
);
uart_byte_rx uart_byte_rx(
.Clk (Clk) ,
.Reset_n (Reset_n) ,
.Baud_Set (4) ,
.uart_rx (uart_rx) ,
.Data (rx_data) ,
.Rx_Done (rx_done)
);
uart_cmd uart_cmd (
.Clk (Clk) ,
.Reset_n (Reset_n) ,
.rx_data (rx_data) ,
.rx_done (rx_done) ,
.ctrl (ctrl) ,
.time_set (time_set)
);
endmodule
子模块——控制LED
//让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。
//8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
//化零为整,设置八个相同时间段,第一个计数器计数每个时间段,位数和每个时间段时间相匹配,Time的值为计数次数,即代表每个时间段是时间长短,计数器位数和Time位数一致;
//第二个计数器计数八个时间段,共8次,需要三位的计数器;
//根据计数器2的值,共八个值,通过八位的Ctrl分别控制八个信号的亮灭状态。
module counter_led_4(
Clk,
Reset_n,
Ctrl,
Time,
Led
);
input Clk;
input Reset_n;
input [7:0]Ctrl;
input [31:0]Time;
output reg [7:0]Led;
reg [31:0]counter;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= #1 0;
else if (counter >= Time - 1)
counter <= #1 0;
else
counter <= #1 counter + 1'b1;
//刚上电的时候,Timne为0,Time - 1 = 32'hFFFFFFFFFFFFFFFF,counter不满足这个值,所以它就一直自加直到加满才会清零,溢出后,进入下一个自加循环,、
//判断counter == Time - 1,
//当实际板级运行的时候,当Time值(25000000)更新时,counter的值已大于该值,只有等其加满溢出后,才能进入下一个循环正常计数
//所以设置counter >= Time - 1,counter值过大时,清零
reg[2:0]counter2;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= #1 0;
else if (counter >= Time - 1)
counter2 <= #1 counter2 + 1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= #1 0;
else case(counter2)
0:Led <= #1 Ctrl[0];
1:Led <= #1 Ctrl[1];
2:Led <= #1 Ctrl[2];
3:Led <= #1 Ctrl[3];
4:Led <= #1 Ctrl[4];
5:Led <= #1 Ctrl[5];
6:Led <= #1 Ctrl[6];
7:Led <= #1 Ctrl[7];
default:Led <= #1 Led;
endcase
endmodule
子模块——发送数据
`timescale 1ns / 1ps
module uart_byte_rx(
Clk ,
Reset_n ,
Baud_Set ,//波特率选择信号,需要和数据发送波特率一致
uart_rx ,//输入串行数据
Data ,//将接收到的数据传送出去,并行输出
Rx_Done //接收完成信号
);
input Clk ;
input Reset_n ;
input [2:0]Baud_Set ;
input uart_rx ;
output reg [7:0]Data ;
output reg Rx_Done ;
//定义两个寄存器,实现边缘检测电路
reg [1:0]uart_rx_r; //先将数据进行存储,两个D触发器
always@(posedge Clk)begin
uart_rx_r[0] <= #1 uart_rx;
uart_rx_r[1] <= #1 uart_rx_r[0];
end
//检测边沿
wire pedge_uart_rx; //上升沿
// assign pedge_uart_rx = ((uart_rx_r[1] = 0)&&(uart_rx_r[0] == 1));
assign pedge_uart_rx = (uart_rx_r == 2'b01);
wire nedge_uart_rx; //下降沿
// assign pedge_uart_rx = ((uart_rx_r[1] = 1)&&(uart_rx_r[0] == 0));
assign nedge_uart_rx = (uart_rx_r == 2'b10);
//波特率设置,在采样时要把每位数据发送的时间分为16段进行采样
reg [8:0] Bps_DR;
always@(*)
case(Baud_Set)
0:Bps_DR = 1000000000/9600/16/20 - 1;
1:Bps_DR = 1000000000/19200/16/20 - 1;
2:Bps_DR = 1000000000/38400/16/20 - 1;
3:Bps_DR = 1000000000/57600/16/20 - 1;
4:Bps_DR = 1000000000/115200/16/20 - 1;
default:Bps_DR = 1000000000/9600/16/20 - 1;
endcase
//产生bps_clk,每一小段,取最中间的值
wire bps_clk_16x;
reg [8:0]div_cnt;
assign bps_clk_16x = (div_cnt == Bps_DR / 2);
//需要一个分频计数器
reg RX_EN; //数据接收的时候,RX_EN处于高电平
reg [2:0]sta_bit;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
RX_EN <= #1 0;
else if(nedge_uart_rx) //当检测到下降沿,即下一位为发送起始位,开始接收数据
RX_EN <= #1 1;
else if(Rx_Done || (sta_bit >= 4)) // 当Rx_Done拉高,或者检测到发送起始位并不是真正的起始位
RX_EN <= #1 0;
//reg [8:0]div_cnt; 分频计数器,计数一个波特率
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
div_cnt <= #1 0;
else if(RX_EN)begin
if(div_cnt == Bps_DR)
div_cnt <= #1 0;
else
div_cnt <= #1 div_cnt + 1'b1;
end
else
div_cnt <= #1 0;
//计数器,传送一八位数据需要十个时间段,每个时间段分16小段,计数16*10 = 160 次,
//每当bps_clk_16x到来一次,计数器加一
reg [7:0]bps_cnt;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
bps_cnt <= #1 0;
else if(RX_EN)begin
if(bps_clk_16x)begin
if(bps_cnt == 160)
bps_cnt <= #1 0;
else
bps_cnt <= #1 bps_cnt + 1'b1;
end
else
bps_cnt <= #1 bps_cnt;
end
else
bps_cnt <= #1 0;
//接收数据,每位数据采样八次,将八次采样值进行累加,判断累加后的值r_data;
//若值为0-3 则该位数据为0,若值为4-7 则该位数据为1。
//reg 位宽width name number
reg[2:0]r_data[7:0]; //表示定义了8个3位的寄存器r_data;定义八个是为了和要接收的八位数据对应,后边再分别定义起始位和结束位
// r_data[0][1] 表示第0个r_data中的第一位数据
//reg [2:0]sta_bit;
reg [2:0]sto_bit;
//接收数据
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)begin
sta_bit <= #1 0;
sto_bit <= #1 0;
r_data[0] <= #1 0;
r_data[1] <= #1 0;
r_data[2] <= #1 0;
r_data[3] <= #1 0;
r_data[4] <= #1 0;
r_data[5] <= #1 0;
r_data[6] <= #1 0;
r_data[7] <= #1 0;
end
else if(bps_clk_16x)begin
case(bps_cnt)
0:begin
sta_bit <= #1 0;
sto_bit <= #1 0;
r_data[0] <= #1 0;
r_data[1] <= #1 0;
r_data[2] <= #1 0;
r_data[3] <= #1 0;
r_data[4] <= #1 0;
r_data[5] <= #1 0;
r_data[6] <= #1 0;
r_data[7] <= #1 0;
end
5,6,7,8,9,10,11:sta_bit <= #1 sta_bit + uart_rx;
21,22,23,24,25,26,27:r_data[0] <= #1 r_data[0] + uart_rx;
37,38,39,40,41,42,43:r_data[1] <= #1 r_data[1] + uart_rx;
53,54,55,56,57,58,59:r_data[2] <= #1 r_data[2] + uart_rx;
69,70,71,72,73,74,75:r_data[3] <= #1 r_data[3] + uart_rx;
85,86,87,88,89,90,91:r_data[4] <= #1 r_data[4] + uart_rx;
101,102,103,104,105,106,107:r_data[5] <= #1 r_data[5] + uart_rx;
117,118,119,120,121,122,123:r_data[6] <= #1 r_data[6] + uart_rx;
133,134,135,136,137,138,139:r_data[7] <= #1 r_data[7] + uart_rx;
149,150,151,152,153,154,155:sto_bit <= #1 sto_bit + uart_rx;
default:;
endcase
end
//输出结果,给到Data
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Data <= #1 0;
else if((bps_cnt == 159 ))begin
Data[0] <= #1 (r_data[0] >= 4)? 1'b1:1'b0;
Data[1] <= #1 (r_data[1] >= 4)? 1'b1:1'b0;
Data[2] <= #1 (r_data[2] >= 4)? 1'b1:1'b0;
Data[3] <= #1 (r_data[3] >= 4)? 1'b1:1'b0;
Data[4] <= #1 (r_data[4] >= 4)? 1'b1:1'b0;
Data[5] <= #1 (r_data[5] >= 4)? 1'b1:1'b0;
Data[6] <= #1 (r_data[6] >= 4)? 1'b1:1'b0;
Data[7] <= #1 (r_data[7] >= 4)? 1'b1:1'b0;
end
// 0:3'b000;
// 1:3'b001;
// 2:3'b010;
// 3:3'b011;
// 4:3'b100;
// 5:3'b101;
// 6:3'b110;
// 7:3'b110;
//0-3 的第二位都为0,4-7的第二位都为1
// always@(posedge Clk or negedge Reset_n)
// if(!Reset_n)
// Data <= 0;
// else if((bps_cnt == 159 ))begin
// Data[0] <= r_data[0][2] ; //等价于 Data[0] <= (r_data[0] >= 4)? 1'b1:1'b0;
// Data[1] <= r_data[1][2] ; //将r_data[1] 第二位的值赋给Data[1]
// Data[2] <= r_data[2][2] ;
// Data[3] <= r_data[3][2] ;
// Data[4] <= r_data[4][2] ;
// Data[5] <= r_data[5][2] ;
// Data[6] <= r_data[6][2] ;
// Data[7] <= r_data[7][2] ;
// end
//给Rx_Done值
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Rx_Done <= #1 0;
else if((div_cnt == Bps_DR) && (bps_cnt == 160 )) //脉冲到来,并且计数到最后一位数159时
Rx_Done <= #1 1;
else
Rx_Done <= #1 0;
endmodule
子模块——将发送的数据与led控制端口进行匹配
`timescale 1ns / 1ps
module uart_cmd(
Clk ,
Reset_n ,
rx_data ,
rx_done ,
ctrl ,
time_set
);
input Clk ;
input Reset_n ;
input [7:0]rx_data ;
input rx_done ;
output reg [7:0]ctrl ;
output reg [31:0]time_set ;
//八个数据,移位寄存器
reg [7:0] data_str [7:0]; ///八个八位的数据
always@(posedge Clk )
if(rx_done)begin //如果接收完一个数据
data_str [7] <= #1 rx_data; //将接收到的数据给7
data_str [6] <= #1 data_str [7];
data_str [5] <= #1 data_str [6];
data_str [4] <= #1 data_str [5];
data_str [3] <= #1 data_str [4];
data_str [2] <= #1 data_str [3];
data_str [1] <= #1 data_str [2];
data_str [0] <= #1 data_str [1];
end
//定义一个rx_done的寄存器r_rx_done,这样r_rx_done一直比rx_done延迟一拍
reg r_rx_done;
always@(posedge Clk )
r_rx_done <= rx_done;
//判断接收到的数据是否符合预期设定的协议
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)begin
ctrl <= #1 0;
time_set <= #1 0;
end
else if(r_rx_done) begin
if((data_str [0] == 8'h55)&&(data_str [1] == 8'hA5)&&(data_str [7] == 8'hF0))begin
time_set[7:0] <= #1 data_str [2];
time_set[15:8] <= #1 data_str [3];
time_set[23:16] <= #1 data_str [4];
time_set[31:24] <= #1 data_str [5];
ctrl <= #1 data_str [6];
end
end
endmodule
功能仿真代码
`timescale 1ns / 1ps
module uart_rx_ctrl_led_tb();
reg Clk ;
reg Reset_n ;
reg uart_rx ;
wire LED ;
uart_rx_ctrl_led uart_rx_ctrl_led(
.Clk (Clk),
.Reset_n (Reset_n),
.uart_rx (uart_rx),
.LED (LED)
);
initial Clk = 1;
always #10 Clk = ~Clk;
initial begin
Reset_n = 0 ;
uart_rx = 1 ;
#201;
Reset_n = 1;
#200;
uart_tx_byte (8'h55) ;//协议第0位
#90000;
uart_tx_byte (8'ha5) ;//协议第1位
#90000;
uart_tx_byte (8'h55) ;//协议第0位
#90000;
uart_tx_byte (8'ha5) ;//协议第1位
#90000;
uart_tx_byte (8'h12) ;//数据第2位
#90000;
uart_tx_byte (8'h34) ;//数据第3位
#90000;
uart_tx_byte (8'h56) ;//数据第4位
#90000;
uart_tx_byte (8'h78) ;//数据第5位
#90000;
uart_tx_byte (8'h9a) ;//数据第6位,给ctrl
#90000;
uart_tx_byte (8'hf0) ;//协议第7位
#90000;
uart_tx_byte (8'h55) ;//协议第0位
#90000;
uart_tx_byte (8'ha5) ;//协议第1位
#90000;
uart_tx_byte (8'h9a) ;//数据第2位
#90000;
uart_tx_byte (8'h78) ;//数据第3位
#90000;
uart_tx_byte (8'h56) ;//数据第4位
#90000;
uart_tx_byte (8'h34) ;//数据第5位
#90000;
uart_tx_byte (8'h12) ;//数据第6位,给ctrl
#90000;
uart_tx_byte (8'hf1) ;//协议第7位
#90000;
$stop;
end
task uart_tx_byte;
input [7:0]tx_data;
begin
uart_rx = 1;
#20;
uart_rx = 0; //起始位
#8680; //115200的波特率发送数据,每位保持时间为8680ns
uart_rx = tx_data[0];
#8680;
uart_rx = tx_data[1];
#8680;
uart_rx = tx_data[2];
#8680;
uart_rx = tx_data[3];
#8680;
uart_rx = tx_data[4];
#8680;
uart_rx = tx_data[5];
#8680;
uart_rx = tx_data[6];
#8680;
uart_rx = tx_data[7];
#8680;
uart_rx = 1; //结束位
#8680;
end
endtask
endmodule
功能仿真结果