FPGA与PC实现串口数据的收发
程序说明:可以将下面两段程序写在一个主模块下面,另外写一个主模块对这两个子模块调用,可实现FPGA与电脑的串口通信回环模式,即:FPGA从PC端接收数据,然后回传给电脑,并且可以通过串口助手进行数据的验证。
串口接收
module uart_rx(
input sclk ,
input s_rst_n ,
input rs232_rx ,
output reg [ 7:0] rx_data ,
output reg po_flag
);
localparam BAUD_END = 5207 ;
localparam BAUD_M = BAUD_END/2 - 1 ;
localparam BIT_END = 8 ;
reg rx_r1 ;
reg rx_r2 ;
reg rx_r3 ;
reg rx_flag ;
reg [12:0] baud_cnt ;
reg bit_flag ;
reg [ 3:0] bit_cnt ;
wire rx_neg ;
assign rx_neg = ~rx_r2 & rx_r3;
always @( posedge sclk) begin
rx_r1 <= rs232_rx;
rx_r2 <= rx_r1;
rx_r3 <= rx_r2;
end
always @ ( posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
rx_flag <= 1'b0;
else if(rx_neg == 1'b1)
rx_flag <= 1'b1;
else if(bit_cnt == 'd0 && baud_cnt == BAUD_END)
rx_flag <= 1'b0;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
baud_cnt <= 'd0;
else if(baud_cnt == BAUD_END)
baud_cnt <= 'd0;
else if(rx_flag == 1'b1)
baud_cnt <= baud_cnt + 1'b1;
else
baud_cnt <= 'd0;
end
always @( posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
bit_flag <= 1'b0;
else if(baud_cnt == BAUD_M)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
bit_cnt <= 'd0;
else if(bit_flag == 1'b1 && bit_cnt == BIT_END)
bit_cnt <= 'd0;
else if(bit_flag == 1'b1)
bit_cnt <= bit_cnt + 1'b1;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
rx_data <= 'd0;
else if(bit_flag == 1'b1 && bit_cnt >= 'd1)
rx_data <= {rx_r2, rx_data[7:1]};
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
po_flag <= 1'b0;
else if(bit_cnt == BIT_END && bit_flag == 1'b1)
po_flag <= 1'b1;
else
po_flag <= 1'b0;
end
endmodule
串口发送
module uart_tx(
input sclk ,
input s_rst_n ,
output reg rs232_tx ,
input tx_trig ,
input [ 7:0] tx_data
);
localparam BAUD_END = 5207 ;
localparam BAUD_M = BAUD_END/2 - 1 ;
localparam BIT_END = 8 ;
reg [ 7:0] tx_data_r ;
reg tx_flag ;
reg [12:0] baud_cnt ;
reg bit_flag ;
reg [ 3:0] bit_cnt ;
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
tx_data_r <= 'd0;
else if (tx_trig == 1'b1 && tx_flag == 1'b0)
tx_data_r <= tx_data;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
tx_flag <= 1'b0;
else if(tx_trig == 1'b1)
tx_flag <= 1'b1;
else if(bit_cnt == BIT_END && bit_flag == 1'b1)
tx_flag <= 1'b0;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
baud_cnt <= 'd0;
else if(baud_cnt == BAUD_END)
baud_cnt <= 'd0;
else if(tx_flag == 1'b1)
baud_cnt <= baud_cnt + 1'b1;
else
baud_cnt <= 'd0;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
bit_flag <= 1'b0;
else if(baud_cnt == BAUD_END)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
bit_cnt <= 'd0;
else if(bit_flag == 1'b1 && bit_cnt == BIT_END)
bit_cnt <= 'd0;
else if(bit_flag == 1'b1)
bit_cnt <= bit_cnt + 1'b1;
end
always @(posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
rs232_tx <= 1'b1;
else if(tx_flag == 1'b1)
case(bit_cnt)
0:rs232_tx <= 1'b0; // start bit
1: rs232_tx <= tx_data_r[0];
2: rs232_tx <= tx_data_r[1];
3: rs232_tx <= tx_data_r[2];
4: rs232_tx <= tx_data_r[3];
5: rs232_tx <= tx_data_r[4];
6: rs232_tx <= tx_data_r[5];
7: rs232_tx <= tx_data_r[6];
8: rs232_tx <= tx_data_r[7];
default :rs232_tx <= 1'b1;
endcase
else
rs232_tx <= 1'b1;
end
endmodule