// 串口接收原理:
// 基本原理:采样
// 思路:一位数据采样多次,统计高低电平出现的次数,次数多的为该位的电平值
// 例:采样7次,每次的结果相加,最终的结果:0、1、2、3为低电平,4、5、6、7为高电平
// 将一个数据分为16段,舍弃前5段和后4段,取中间7段进行采样
// 起始位检测:通过边沿检测电路
// Create Date: 2024/04/05 13:44:12
// Design Name: hilary
// Module Name: uart_byte_rx
// 串口接收原理:
// 基本原理:采样
// 思路:一位数据采样多次,统计高低电平出现的次数,次数多的为该位的电平值
// 例:采样7次,每次的结果相加,最终的结果:0、1、2、3为低电平,4、5、6、7为高电平
// 将一个数据分为16段,舍弃前5段和后4段,取中间7段进行采样
// 起始位检测:通过边沿检测电路
// 波特率设为:9600
// 计数器:1000000000/9600/16/20 = 325
// 计数325产生一个bps_clk
// 波特率设为:115200
// 计数器:1000000000/115200/16/20 = 27
// 计数27产生一个bps_clk
// 波特率设为:9600
// 计数器:1000000000/9600/16/20 = 325
// 计数325产生一个bps_clk
// 波特率设为:115200
// 计数器:1000000000/115200/16/20 = 27
// 计数27产生一个bps_clk
module uart_byte_rx(
Clk,
Reset_n,
Baud_Set,
uart_rx,
Data,
Rx_Done);
input Clk;
input Reset_n;
input [2:0] Baud_Set;
input uart_rx;
output reg [7:0] Data;
output reg Rx_Done;
//边沿检测
reg [1:0] uart_rx_r;
always @(posedge Clk) begin
uart_rx_r[0] <= uart_rx;
uart_rx_r[1] <= uart_rx_r[0];
end
wire pedge_uart_rx;
// assign pedge_uart_rx = ((uart_rx_r[1] == 0) && (uart_rx_r[1] == 1));
assign pedge_uart_rx = (uart_rx_r == 2 'b01);
wire nedge_uart_rx;
// assign nedge_uart_rx = ((uart_rx_r[1] == 1) && (uart_rx_r[1] == 1));
assign nedge_uart_rx = (uart_rx_r == 2 'b10);
// 波特率设置
reg [8:0] Bps_DR;
always@(*)
case (Baud_Set)
0 : Bps_DR = 1000000000/9600/16/20 - 1;
1 : Bps_DR = 1000000000/19200/16/20 - 1;
2 : Bps_DR = 1000000000/38400/16/20 - 1;
3 : Bps_DR = 1000000000/57600/16/20 - 1;
4 : Bps_DR = 1000000000/115200/16/20 - 1;
default: Bps_DR = 1000000000/9600/16/20 - 1;
endcase
wire bps_clk_16x;
assign bps_clk_16x = (div_cnt == Bps_DR / 2);
reg [8:0] div_cnt;
//使能电平计数信号
reg RX_EN;
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
RX_EN <= 0;
end
else if (nedge_uart_rx) begin
RX_EN <= 1;
end
else if (Rx_Done || (sta_bit >= 4)) begin
RX_EN <= 0;
end
end
//分频计数器
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
div_cnt <= 0;
end
else if (RX_EN) begin
if (div_cnt == Bps_DR) begin
div_cnt <= 0;
end
else
div_cnt <= div_cnt + 1 'b1;
end
else
div_cnt <= 0;
end
reg [7:0] bps_cnt ;
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
bps_cnt <= 0;
end
else if (RX_EN) begin
if (bps_clk_16x) begin
if (bps_cnt == 160) begin
bps_cnt<= 0;
end
else
bps_cnt <= bps_cnt + 1 'b1;
end
else
bps_cnt <= bps_cnt;
end
else
bps_cnt <= 0;
end
//接收数据
// reg width name number 二维寄存器
// reg 位宽 名字 数量
reg [2:0] r_data[7:0];
reg [2:0] sta_bit;
reg [2:0] sto_bit;
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
sta_bit <= 0;
sto_bit <= 0;
r_data[0] <= 0;
r_data[1] <= 0;
r_data[2] <= 0;
r_data[3] <= 0;
r_data[4] <= 0;
r_data[5] <= 0;
r_data[6] <= 0;
r_data[7] <= 0;
end
else if(bps_clk_16x) begin
case (bps_cnt)
0 : begin
sta_bit <= 0;
sto_bit <= 0;
r_data[0] <= 0;
r_data[1] <= 0;
r_data[2] <= 0;
r_data[3] <= 0;
r_data[4] <= 0;
r_data[5] <= 0;
r_data[6] <= 0;
r_data[7] <= 0;
end
5,6,7,8,9,10,11 : sta_bit <= sta_bit + uart_rx;
21,22,23,24,25,26,27 : r_data[0] <= r_data[0] + uart_rx;
37,38,39,40,41,42,43 : r_data[1] <= r_data[1] + uart_rx;
53,54,55,56,57,58,59 : r_data[2] <= r_data[2] + uart_rx;
69,70,71,72,73,74,75 : r_data[3] <= r_data[3] + uart_rx;
85,86,87,88,89,90,91 : r_data[4] <= r_data[4] + uart_rx;
101,102,103,104,105,106,107 : r_data[5] <= r_data[5] + uart_rx;
117,118,119,120,121,122,123 : r_data[6] <= r_data[6] + uart_rx;
133,134,135,136,137,138,139 : r_data[7] <= r_data[7] + uart_rx;
149,150,151,152,153,154,155 : sto_bit <= sto_bit + uart_rx;
default: ;
endcase
end
end
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
Data <= 0;
end
else if (bps_clk_16x && (bps_cnt == 159) ) begin
Data[0] <= (r_data[0] >= 4)? 1 'b1:1 'b0;
Data[1] <= (r_data[1] >= 4)? 1 'b1:1 'b0;
Data[2] <= (r_data[2] >= 4)? 1 'b1:1 'b0;
Data[3] <= (r_data[3] >= 4)? 1 'b1:1 'b0;
Data[4] <= (r_data[4] >= 4)? 1 'b1:1 'b0;
Data[5] <= (r_data[5] >= 4)? 1 'b1:1 'b0;
Data[6] <= (r_data[6] >= 4)? 1 'b1:1 'b0;
Data[7] <= (r_data[7] >= 4)? 1 'b1:1 'b0;
end
end
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
Rx_Done <= 0;
end
else if ((div_cnt == Bps_DR/2) && (bps_cnt == 160))begin
Rx_Done <= 1;
end
else
Rx_Done <= 0;
end
endmodule
仿真测试:
module uart_byte_re_tb();
reg Clk;
reg Reset_n;
wire [2:0] Baud_Set;
reg uart_rx;
wire [7:0] Data;
wire Rx_Done;
assign Baud_Set = 4;
uart_byte_rx uart_byte_rx(
Clk,
Reset_n,
Baud_Set,
uart_rx,
Data,
Rx_Done);
initial Clk = 1;
always#10 Clk = ~Clk;
initial begin
Reset_n <= 0;
#201;
Reset_n <= 1;
#200;
uart_tx_byte(8 'h5a);
#90000;
uart_tx_byte(8 'ha5);
#90000;
uart_tx_byte(8 'h86);
#90000;
$stop;
end
task uart_tx_byte;
input [7:0] tx_data;
begin
uart_rx = 1;
#20;
uart_rx = 0;
#8680;
uart_rx = tx_data[0];
#8680;
uart_rx = tx_data[1];
#8680;
uart_rx = tx_data[2];
#8680;
uart_rx = tx_data[3];
#8680;
uart_rx = tx_data[4];
#8680;
uart_rx = tx_data[5];
#8680;
uart_rx = tx_data[6];
#8680;
uart_rx = tx_data[7];
#8680;
uart_rx = 1;
#8680;
end
endtask
endmodule
结果: