每一次采样应该在每一小段的最中间
##初次设计
源代码:
module uart_byte_rx(
Clk,
Reset_n,
Baud_Set,
uart_rx,
Data,
Rx_Done
);
input Clk;
input Reset_n;
input Baud_Set;
input uart_rx;
output reg [7:0] Data;
output reg Rx_Done;
reg [1:0] uart_rx_r; //两个D触发器作为边沿检测
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[0] == 1)); [1]是前一个时刻,[0]是新来的一个时刻 D触发器
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[0] == 0));
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 RX_EN;
always @(posedge Clk or negedge Reset_n)
if(!Reset_n)
RX_EN <= 0;
else if (nedge_uart_rx)
RX_EN <= 1;
else if ((Rx_Done)|| (sta_bit >= 4)) //接收完或者sta不是正确的起始位
RX_EN <= 0;
reg [8:0] div_cnt; //分频器,分出每一次采样的时间。
always @(posedge Clk or negedge Reset_n)
if(!Reset_n)
div_cnt <= 0; //检测到下降沿的时候开始计数
else if (RX_EN)begin /*else if (nedge_uart_rx)此语句不成立,因为nedge是一个瞬时的过程,只维持一个时钟周期,
div只能加一次。需要以nedge为起点来使能div,知道数据接收完成或者发现不是起始位的时候再来停止。
所以需要再产生一个使能的电平计数控制信号RX_EN*/
if(div_cnt == Bps_DR)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
end //返回上方bps_clk_16x
else
div_cnt <= 0;
reg [7:0] bps_cnt;
always @(posedge Clk or negedge Reset_n)
if(!Reset_n)
bps_cnt <= 0;
else if (RX_EN) begin
if(bps_clk_16x)begin
if(bps_cnt == 160)
bps_cnt <= 0;
else
bps_cnt <= bps_cnt + 1'b1; //采样信号来了加一
end
else
bps_cnt <= bps_cnt; //采样信号没来保持不变
end
else
bps_cnt <= 0;
//采样数据接收模块
reg [2:0] r_data [7:0]; // reg with name number 有8个位宽为[2:0]的r_data寄存器。
// r_data[0][1] 意味着取第零个寄存器的第一位。
reg [2:0] sta_bit;
reg [2:0] sto_bit;
always @(posedge Clk or negedge Reset_n)
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 : sta_bit <=sta_bit + 1'b1;
6 : sta_bit <=sta_bit + 1'b1;
7 : sta_bit <=sta_bit + 1'b1;*/
5,6,7,8,9,10,11 : sta_bit <= sta_bit <=sta_bit + uart_rx;// 从第五位开始计数,累加情况取决于uart_rx给出的状态,若最后 sta_bit数据大于四,则判断为高电平
// 每一数据采样15次 下一数据的采样开始为16, 有效范围则在21开始。
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
always @(posedge Clk or negedge Reset_n) //数据状态判定模块
if(!Reset_n)
Data <= 0;
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
always @(posedge Clk or negedge Reset_n)
if(!Reset_n)
Rx_Done <= 0;
else if ((div_cnt == Bps_DR/2) && (bps_cnt == 160))
Rx_Done <= 1;
else
Rx_Done <= 0;
endmodule
TB文件:
`timescale 1ns / 1ps
module uart_byte_rx_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;
uart_rx = 1;
#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
此处可改写为:
Data[0] <= r_data[0][2];
// Data[1] <= r_data[1][2];
// Data[2] <= r_data[2][2];
// Data[3] <= r_data[3][2];
// Data[4] <= r_data[4][2];
// Data[5] <= r_data[5][2];
// Data[6] <= r_data[6][2];
// Data[7] <= r_data[7][2];