串口发送
`timescale 1ns / 1ns
module uart_send
#( parameter CLK_FREQ = 50000000,
parameter BPS = 115200
)
(sys_clk,
reset_n,
uart_data,
tx_go,
uart_tx,
uart_tx_busy
);
input sys_clk;
input reset_n;
input [7:0]uart_data;
input tx_go;
output reg uart_tx;
output uart_tx_busy;
localparam BPS_MAX = CLK_FREQ/BPS;
reg [1:0] tx_go_r;
reg tx_en;
reg [3:0] tx_cnt;
reg [15:0] bps_clk;
//检测tx_go的上升沿
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
tx_go_r<=0;
else
begin
tx_go_r[0]<=tx_go;
tx_go_r[1]<=tx_go_r[0];
end
end
//tx_en使能控制
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
tx_en<=0;
else if(tx_go_r==2'b01)
tx_en<=1;
else if(tx_cnt==9&&bps_clk==BPS_MAX-1)
tx_en<=0;
else tx_en<=tx_en;
end
//bps_clk分频
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
bps_clk<=0;
else if(tx_en)
begin
if(bps_clk==BPS_MAX-1)
bps_clk<=0;
else bps_clk<=bps_clk+1'b1;
end
else bps_clk<=0;
end
//发送位计数
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
tx_cnt<=0;
else if (tx_en)
begin
if(tx_cnt==9&&bps_clk==BPS_MAX-1)
tx_cnt<=0;
else if(bps_clk==BPS_MAX-1)
tx_cnt<=tx_cnt+1'b1;
else tx_cnt<=tx_cnt;
end
else tx_cnt<=0;
end
//发送控制
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
uart_tx<=1;
else if (tx_en)
begin
case(tx_cnt)
0:uart_tx<=0;
1:uart_tx<=uart_data[0];
2:uart_tx<=uart_data[1];
3:uart_tx<=uart_data[2];
4:uart_tx<=uart_data[3];
5:uart_tx<=uart_data[4];
6:uart_tx<=uart_data[5];
7:uart_tx<=uart_data[6];
8:uart_tx<=uart_data[7];
9:uart_tx<=1;
endcase
end
else uart_tx<=1;
end
assign uart_tx_busy = tx_en;
endmodule
串口接收
module uart_recv
#( parameter CLK_FREQ = 50000000,
parameter BPS = 115200
)
(
sys_clk,
reset_n,
uart_tx,
rx_data,
rx_done
);
input sys_clk;
input reset_n;
input uart_tx;
output reg [7:0] rx_data;
output reg rx_done;
localparam BPS_MAX = CLK_FREQ/BPS;
reg [15:0] bps_clk;
reg [1:0] uart_tx_r;
reg [3:0] rx_cnt;
wire start_flag;
reg uart_en;
reg [7:0] uart_din;
//uart_tx下降沿检测,检测到下降沿后,start_flag拉高一个周期
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
uart_tx_r<=2'b00;
else
begin
uart_tx_r[0]<=uart_tx;
uart_tx_r[1]<=uart_tx_r[0];
end
end
assign start_flag = (uart_tx_r==2'b10)?1:0;
//UART_EN使能信号控制
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
uart_en<=0;
else if(start_flag)
uart_en<=1;
else if(rx_cnt==9&&bps_clk==BPS_MAX/2-1)
uart_en<=0;
else uart_en<=uart_en;
end
//bps_clk 分频
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
bps_clk<=0;
else if(uart_en)
begin
if(bps_clk==BPS_MAX-1)
bps_clk<=0;
else bps_clk<=bps_clk+1'b1;
end
else bps_clk<=0;
end
//rx_cnt 计数
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
rx_cnt<=0;
else if(uart_en)
begin
if(rx_cnt==9&&bps_clk==BPS_MAX/2-1)
rx_cnt<=0;
else if(bps_clk==BPS_MAX-1)
rx_cnt<=rx_cnt+1'b1;
else
rx_cnt<=rx_cnt;
end
end
//数据接收
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
uart_din<=0;
else if(bps_clk==BPS_MAX/2-1)
begin
case(rx_cnt)
0:uart_din<=0;
1:uart_din[0]<=uart_tx;
2:uart_din[1]<=uart_tx;
3:uart_din[2]<=uart_tx;
4:uart_din[3]<=uart_tx;
5:uart_din[4]<=uart_tx;
6:uart_din[5]<=uart_tx;
7:uart_din[6]<=uart_tx;
8:uart_din[7]<=uart_tx;
default:uart_din<=uart_din;
endcase
end
else uart_din<=uart_din;
end
//接受完成标志位
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
rx_done<=0;
else if(rx_cnt==9&&bps_clk==BPS_MAX/2-1)
rx_done<=1;
else
rx_done<=0;
end
//接受数据输出
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
rx_data<=0;
else if (rx_done)
rx_data<=uart_din;
else
rx_data<=rx_data;
end
endmodule
环回:
module uart_loop
(
recv_data,
recv_done,
sys_clk,
reset_n,
send_busy,
send_data,
send_en
);
input [7:0] recv_data;
input recv_done;
input sys_clk;
input reset_n;
input send_busy;
output reg [7:0] send_data;
output reg send_en;
reg [1:0] recv_done_r;
reg send_ready;
//将recv_done寄存两拍,检测rx_done的上升沿
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
recv_done_r<=0;
else
begin
recv_done_r[0]<= recv_done;
recv_done_r[1]<= recv_done_r[0];
end
end
//检测到 rx_done的上升沿后,发出准备信号
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
begin
send_ready<=0;
end
else if(recv_done_r==2'b01)
begin
send_ready<=1;
end
else if(!send_busy)
send_ready<=0;
end
// 控制
always@(posedge sys_clk or negedge reset_n)
begin
if(!reset_n)
begin
send_data<=0;
send_en<=0;
end
else if(send_ready==1&&!send_busy)
begin
send_data<=recv_data;
send_en<=1;
end
else
begin
send_data<=send_data;
send_en<=0;
end
end
endmodule
top:
module uart_top(
sys_clk,
reset_n,
uart_rxd,
uart_txd
);
input sys_clk;
input reset_n;
input uart_rxd;
output uart_txd;
wire [7:0] recv_data;
wire recv_done;
wire [7:0] send_data;
wire send_busy;
wire send_en;
parameter CLK_FREQ = 50000000;
parameter BPS = 115200;
uart_send
#( .CLK_FREQ(CLK_FREQ),
.BPS(BPS)
)
u_uart_send
(.sys_clk(sys_clk),
.reset_n(reset_n),
.uart_data(send_data),
.tx_go(send_en),
.uart_tx(uart_txd),
.uart_tx_busy(send_busy)
);
uart_recv
#( .CLK_FREQ(CLK_FREQ),
.BPS(BPS)
)
u_uart_recv
(
.sys_clk(sys_clk),
.reset_n(reset_n),
.uart_tx(uart_rxd),
.rx_data(recv_data),
.rx_done(recv_done)
);
uart_loop u_uart_loop
(
.recv_data(recv_data),
.recv_done(recv_done),
.sys_clk(sys_clk),
.reset_n(reset_n),
.send_busy(send_busy),
.send_data(send_data),
.send_en(send_en)
);
endmodule