参考bilibili“野火科技”视频改编,作为笔记复习参考
module uart_rec(
//成了
input clk,
input reset,
input rx,
output reg [7:0]Po_data,
output reg Po_flag
);
reg rx1;
reg rx2;
reg rx3;
reg start_flag;
reg work_en;
reg [15:0]baud_cnt;
// reg bit_flag;
reg [3:0]bit_cnt;
reg [7:0]rx_data;
reg rx_flag;
parameter CLK_FREQ = 100000000; //系统时钟频率
parameter UART_BPS = 115200; //串口波特率
parameter BAUD_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率,
//需要对系统时钟计数BPS_CNT次
always @(posedge clk or negedge reset) begin
if(!reset) begin
rx1 <= 1'b1;
rx2 <= 1'b1;
rx3 <= 1'b1;
end
else begin
rx1 <= rx;
rx2 <= rx1;
rx3 <= rx2;
end
end
//获取rx下降沿
always @(posedge clk or negedge reset) begin
if(!reset)
start_flag <= 1'b0;
else
start_flag <= rx3 & ~rx2;
end
//什么时候 工作、接受数据完成?
always @(posedge clk or negedge reset) begin
if(!reset) begin
work_en <= 1'b0;
rx_flag <= 1'b0;
end
else if(start_flag == 1'b1)
work_en <= 1'b1;
else if(bit_cnt == 4'd8 && baud_cnt == (BAUD_CNT/2)+1) begin
work_en <= 0;
rx_flag <= 1'b1;
end
else begin
work_en <= work_en ;
rx_flag <= 1'b0;
end
end
// 定时
always @(posedge clk or negedge reset) begin
if(!reset) begin
baud_cnt <= 16'd0;
end
else if(work_en == 1'b1) begin
if(baud_cnt == BAUD_CNT-1) begin
baud_cnt <= 16'd0;
end
else begin
baud_cnt <= baud_cnt + 16'd1;
end
end
else begin
baud_cnt <= 16'd0;
end
end
// 抓取的是第几个数据
always @(posedge clk or negedge reset) begin
if(!reset) begin
bit_cnt <= 4'd0;
end
else if(work_en == 1'b1) begin
if(baud_cnt == BAUD_CNT-1) begin
bit_cnt <= bit_cnt + 4'd1;
end
else begin
bit_cnt <= bit_cnt;
end
end
else begin
bit_cnt <= 4'd0;
end
end
//抓取数据
always @(posedge clk or negedge reset) begin
if(!reset)
rx_data <= 8'd0;
else if(baud_cnt == BAUD_CNT/2) begin
case(bit_cnt)
4'd1:rx_data[0] <= rx;
4'd2:rx_data[1] <= rx;
4'd3:rx_data[2] <= rx;
4'd4:rx_data[3] <= rx;
4'd5:rx_data[4] <= rx;
4'd6:rx_data[5] <= rx;
4'd7:rx_data[6] <= rx;
4'd8:rx_data[7] <= rx;
default:rx_data <= 8'd0;
endcase
end
else
rx_data <= rx_data;
end
//输出数据
always @(posedge clk or negedge reset) begin
if(!reset) begin
Po_data <= 8'd0;
Po_flag <= 1'b0;
end
else if(rx_flag == 1'b1) begin
Po_data <= rx_data;
Po_flag <= 1'b1;
end
else begin
Po_data <= 8'd0;
Po_flag <= 1'b0;
end
end
endmodule