串口输出程序例程
`timescale 1ns / 1ps
module serial(
input [7:0]Data,
input Send_en,//为1的时候开始工作
input CLK,
input Rest,
input [2:0]Baud_set,//设置波特率
output reg uart_tx,
output reg Tx_done//传输完成标志位
);
reg [17:0]baud; //波特率
reg [17:0]cnt; //发送一位数据的计数时间
reg [3:0]bps_cnt; // 循环8位数据
/*---------------设定波特率(默认位9600)---------------*/
always@(*)
if(!Rest)
baud<=0;
else
case(Baud_set)
0:baud=1000000000/9600/20;
1:baud=1000000000/19200/20;
2:baud=1000000000/38400/20;
3:baud=1000000000/57600/20;
4:baud=1000000000/115200/20;
default:baud=1000000000/9600/20;
endcase
/*---------------计算发送一位需要的时间---------------*/
always@(posedge CLK or negedge Rest)
if(!Rest)
cnt<=0;
else if(Send_en)
begin
if(cnt==baud-1)
cnt<=0;
else
cnt<=cnt+1'b1;
end
else
cnt<=0;
/*---------------开始进行8位的数据传输---------------*/
always@(posedge CLK or negedge Rest)
if(!Rest)
bps_cnt<=0;
else if(Send_en)//只有当Send_en=1时,串口才打开,才能执行传输
begin
if(cnt==baud-1)
begin
if(bps_cnt==11)//除了8位数据位,还有起始位和结束位,起始位是下降沿、结束位是上升沿(上升沿需要持续一个位周期,因此需要占两个)因此总共是11个
bps_cnt<=0;
else
bps_cnt<=bps_cnt+1'b1;
end
end
else //Send_en=0,串口关闭
bps_cnt<=0;
always@(posedge CLK or negedge Rest)
if(!Rest) //复位,所有控制都清零
begin
uart_tx<=1'b1;
Tx_done<=0;
end
else if(Send_en) //当Send_en是1的时候,串口执行
case(bps_cnt)
0:begin uart_tx<=0;Tx_done<=1'b0; end//uart_tx=0,起始位(因位默认空闲的时候uart_tx是高电平);Tx_done取0,表示还没传输完成
1:uart_tx<=Data[0];
2:uart_tx<=Data[1];
3:uart_tx<=Data[2];
4:uart_tx<=Data[3];
5:uart_tx<=Data[4];
6:uart_tx<=Data[5];
7:uart_tx<=Data[6];
8:uart_tx<=Data[7];
9:uart_tx<=1; //结束标志位
10:begin uart_tx<=1;Tx_done<=1'b1; end//结束标志位保持一个位周期,避免与空闲状态的uart_tx=1混淆;Tx_done拉高,表示传输完成;
default:uart_tx<=1; //空闲状态
endcase
else
begin uart_tx<=1;end
endmodule
test_bench
`timescale 1ns / 1ps
module serial_tb( );
reg CLK;
reg [7:0]Data;
reg Send_en;
reg Rest;
reg [2:0]Baud_set;
wire uart_tx;
wire Tx_done;
serial serial
(
.Data(Data),
.Send_en(Send_en),
.CLK(CLK),
.Rest(Rest),
.Baud_set(Baud_set),//波特率
.uart_tx(uart_tx),
.Tx_done(Tx_done)
);
initial CLK=0;
always #10 CLK=~CLK;
initial
begin
Rest=0;
Data=0;
Send_en=0;
Baud_set=4; //波特率设置为9600
#201;
Rest=1;
#100;
Data=8'h57; //串口传输数据是16进制的57
Send_en=1; //开始串口传输
#20;
@(posedge Tx_done); //一直等待Tx_done的上升沿,若未到来,则一直等待
Send_en=0; //结束串口传输
#20000;
Data=8'h75;
Send_en=1;
#20;
@(posedge Tx_done);
#20000;
Send_en=0;
$stop;
end
endmodule
从输出波形可以看出符合预期要求