Date是8位并行的传输数据,通过输出端口uart_tx串行输出。
Baud_set代表波特率的种类代号(0,1,2,3,4···)。
send_en表示发送数据指令,高电平时发送数据。
Tx_Done表示一个Date数据发送结束时的反馈,高电平代表发送数据完成。
uart_tx传输信号形式:起始位低电平,终止位高电平,中间8位传输数据。
下面展示代码
module uart_byte_tx(
clk,
rst_n,
Date,
send_en,
Baud_set,
uart_tx,
Tx_Done
);
input clk,rst_n;
input [7:0]Date;
input send_en;
input [2:0]Baud_set;
output reg uart_tx;
output reg Tx_Done;
//对波特率进行分配,便于计数
reg [17:0]byte_DR;
always@(*)begin
case(Baud_set)
0: byte_DR = 1_000_000_000/9600/20;
1: byte_DR = 1_000_000_000/19200/20;
2: byte_DR = 1_000_000_000/38400/20;
3: byte_DR = 1_000_000_000/57600/20;
4: byte_DR = 1_000_000_000/115200/20;
default: byte_DR = 1_000_000_000/115200/20;
endcase
end
//计数一个数据位
reg [17:0]cnt0;
// wire end_cnt0;
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
cnt0 <= 0;
end
else if(send_en)begin
if(cnt0 == byte_DR - 1)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
else
cnt0 = 0;
// assign send_en = 1;
// assign end_cnt0 = send_en && cnt0 == byte_DR - 1;
//计数8个传输位和2个起始终止位,共计10位
reg [3:0]cnt1;
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
cnt1 <= 0;
end
else if(send_en)begin
if(cnt0 == 1)begin
/*
if(cnt0 == byte_DR - 1)这里据说是uart延时一个数据位发送了,不懂啊,但是cnt1后面出现了11。ps:解决了是因为测试文件写错了。没有在@(posedge Tx_Done)后面加上send_en=0;
/*
if(cnt1 == 11)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
else
cnt1 <= 0;
// assign add_cnt1 = end_cnt0;
// assign end_cnt1 = send_en && cnt1== 11 - 1;
//赋值10个数据位
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
uart_tx <= 1;
Tx_Done <= 0;
end
else begin
case(cnt1)
0: Tx_Done <= 0;
1: uart_tx <= 0;
2: uart_tx <= Date[0];
3: uart_tx <= Date[1];
4: uart_tx <= Date[2];
5: uart_tx <= Date[3];
6: uart_tx <= Date[4];
7: uart_tx <= Date[5];
8: uart_tx <= Date[6];
9: uart_tx <= Date[7];
10: uart_tx <= 1'b1;
11:begin uart_tx <= 1;Tx_Done <= 1; end
default:uart_tx <= 1;
endcase
end
end
endmodule
测试代码tb
`timescale 1ns / 1ns
module uart_byte_tx_tb(
);
reg clk,rst_n;
reg [7:0]Date;
reg send_en;
reg [2:0]Baud_set;
wire uart_tx;
wire Tx_Done;
uart_byte_tx inst1(
.clk(clk),
.rst_n(rst_n),
.Date(Date),
.send_en(send_en),
.Baud_set(Baud_set),
.uart_tx(uart_tx),
.Tx_Done(Tx_Done)
);
initial clk = 1;
always #10 clk = ~clk;
initial begin
rst_n = 0;
send_en = 0;
Date = 0;
Baud_set = 4;
#201;
rst_n = 1;
#100;
send_en = 1;
Date = 8'b1001_0110;
#20;
@(posedge Tx_Done);
send_en = 0;
#20000;
send_en = 1;
Date = 8'b0110_1001;
#20;
@(posedge Tx_Done);
send_en = 0;
#20000;
$stop;
end
endmodule
仿真结果图