1.用三个状态实现串口多个字节的数据发送
module uart_send_data( clk,
reset,
uart_tx,
data40,
trans_go,
trans_done,
byte_number
);
input clk,reset;//时钟,复位
input [2:0]byte_number;//所需传输字节数
input [39:0]data40;//所需传输数据
input trans_go;//开始发送数据请求信号
output uart_tx;//数据拆为多个8位发送
output reg trans_done;//数据发送完成信号
reg [7:0]data;
reg send_go;
wire tx_done;
uart_send ins1(.clk(clk),
.reset(reset),
.send_go(send_go),
.data(data),
.baud_set(4),
.uart_tx(uart_tx),
.tx_done(tx_done)
);
reg [2:0]state;
reg [5:0]cnt;
reg [39:0]r_data40;
always@(posedge trans_go )
if(trans_go)
r_data40=data40;
else
r_data40=r_data40;//发送请求信号来,就将数据存储到r_data40中
always@(posedge clk or negedge reset)
if(!reset)
cnt<=0;
else if(tx_done)begin
if(cnt==byte_number-1)
cnt<=0;
else
cnt<=cnt+1'b1;
end//所需传输数据data40发送完成,就将计数器清0.每次发送8位完成后cnt加一
always@(posedge tx_done)
r_data40={r_data40[7:0],r_data40[39:8]};//每发送完一次8位数据,就将r_data40右移8位
always@(posedge clk or negedge reset)
if(!reset)begin
state<=0;
data<=0;
send_go<=0;
state<=0;
trans_done<=0;
end
else begin
case(state)
0:begin
trans_done<=0;
if(trans_go)begin
state<=1;
data<=r_data40[7:0];
send_go<=1;
end
else
state<=0;
end//此状态下,等待trans_go。trans_go来临时,进入下一状态,同时启动发送8位数据
1:begin
if(cnt==byte_number-1)begin
state<=2;
data<=r_data40[7:0];
send_go<=1;
end//满足条件,进入下一状态,发最后8位信号
else begin
if(tx_done)begin
data<=r_data40[7:0];
send_go<=1;
state<=1;
end
else begin
data<=data;
send_go<=0;
state<=1;
end
end
end//
2:begin
if(tx_done) begin
state<=0;
send_go<=0;
trans_done<=1;//判断最后8位是否发完,发完回到0状态,继续等待
end
else begin
state<=2;
send_go<=0;
trans_done<=0;
end
end
endcase
end
endmodule
2.串口发送模块uart_send的代码
module uart_send(clk,
reset,
send_go,
data,
baud_set,
uart_tx,
tx_done
);
input clk,reset,send_go;
input [2:0]baud_set;
input[7:0] data;
output reg uart_tx,tx_done;
reg [7:0]r_data;
always@(posedge clk )
if(send_go)
r_data<=data;
else
r_data<=r_data;//数据锁存
reg send_en;
always@(posedge clk or posedge reset)
if(!reset)
send_en<=0;
else if(send_go)
send_en<=1;
else if(tx_done)
send_en<=0;//外部发送信号控制内部发送信号
reg[17 :0] bps_DR;
always@(posedge clk or posedge reset)
if(!reset)
bps_DR <= 17 'd5207;
else begin
case(baud_set)
0:bps_DR <= 17'd5207;
1:bps_DR <= 17'd2603;
2:bps_DR <= 17'd1301;
3:bps_DR <= 17'd867;
4:bps_DR <= 17'd433;
default:bps_DR <= 17'd5207;
endcase
end//波特率选择控制
reg [17:0]counter;
always@(posedge clk or posedge reset)
if(!reset)
counter<=0;
else if(send_en)begin
if(counter==bps_DR)
counter<=0;
else
counter<=counter+1'b1;
end
else
counter<=0;
reg [4:0]counter1;
always@(posedge clk or posedge reset)
if(!reset)
counter1<=1;
else if(send_en)begin
if(counter==1)begin
if(counter1==11)
counter1<=0;
else
counter1<=counter1+1'b1;
end
end
else
counter1<=0;
always@(posedge clk or posedge reset)
if(!reset)begin
uart_tx<=0;
end
else begin
case(counter1)
1:begin uart_tx<=0;end
2:uart_tx<=r_data[0];
3:uart_tx<=r_data[1];
4:uart_tx<=r_data[2];
5:uart_tx<=r_data[3];
6:uart_tx<=r_data[4];
7:uart_tx<=r_data[5];
8:uart_tx<=r_data[6];
9:uart_tx<=r_data[7];
10:uart_tx<=1;
11:begin uart_tx<=1;end
default:uart_tx<=1;
endcase
end//发送数据
always@(posedge clk or posedge reset)
if(!reset)
tx_done<=0;
else if(counter1==11&&counter==2)
tx_done<=1;
else
tx_done<=0;//发送完成信号
endmodule
3.仿真文件
module uart_send_data_tb();
reg clk,reset;
reg [39:0]data40;
reg trans_go;
reg [2:0]byte_number;
wire uart_tx;
wire trans_done;
uart_send_data uart_send_data(clk,
reset,
uart_tx,
data40,
trans_go,
trans_done,
byte_number
);
initial clk=0;
always#10 clk=~clk;
initial begin
reset=0;
data40=0;
trans_go=0;
byte_number=5;
#201
reset=1;
#200;
data40=40'h123456789a;
trans_go=1;
#20;
trans_go=0;
@(posedge trans_done)
#20000;
data40=40'ha987654321;
trans_go=1;
#20;
trans_go=0;
@(posedge trans_done)
#20000;
$stop;
end
endmodule
4.仿真结果