大致思路如下:
【1】在复位状态下,寄存器清零。
【2】将波特率时钟分成16段(即计数满16次产生一个ce_1脉冲),在计数满八次时产生ce_1_mid脉冲信号,进行采样(中间的数据比较稳定),将采用的数据放到移位寄存器in_sync中进行存储,同时会将数据缓存到大。data_buf进行存储,然后传送到输出端。
//---------------------------------------------------------------------------------------
//out<={in,out[3:1]}; 这是在将out[3:0]右移一位,舍弃最低位out[0]同时高位移入in。
// uart receive module
//
//---------------------------------------------------------------------------------------
module uart_rx
(
clock,
reset,
ce_16,
ser_in,
rx_data,
new_rx_data
);
input clock;
input reset;
input ce_16; // 波特率时钟产生
input ser_in; // 串行数据输入
output [7:0] rx_data; // 接收的新数据
output new_rx_data; // 接受新数据的信号
// internal wires
wire ce_1;
wire ce_1_mid; // 时钟启用在每个位的中间-用于采样数据(对每一位数据进行采样时,一般情况下认为数据中间的数据是最稳定的)
// internal registers
reg [7:0] rx_data;
reg new_rx_data;
reg [1:0] in_sync;
reg rx_busy;
reg [3:0] count16;
reg [3:0] bit_count;
reg [7:0] data_buf;
// 异步输入信号被采样两次
always @ (posedge clock or posedge reset)
begin
if (reset)
in_sync <= 2'b11;
else
in_sync <= {in_sync[0], ser_in};//左移一位,舍弃移位寄存器的高位in_sync[1],同时写入串行输入数据写入低位
end
// 计数器产生 ce_1 和ce_1_mid 脉冲信号.
//此计数器用于在接收端不接收时检测起始位,并在接收端对采样周期进行计数
always @ (posedge clock or posedge reset)
begin
if (reset)
count16 <= 4'b0;
else if (ce_16)
begin
if (rx_busy | (in_sync[1] == 1'b0))???//这里怎么理解
count16 <= count16 + 4'b1;
else
count16 <= 4'b0;
end
end
//ce_1信号的产生
assign ce_1 = (count16 == 4'b1111) & ce_16;
// ce_1_mid信号的产生
assign ce_1_mid = (count16 == 4'b0111) & ce_16;
// rx_busy信号
always @ (posedge clock or posedge reset)
begin
if (reset)
rx_busy <= 1'b0;
else if (~rx_busy & ce_1_mid)
rx_busy <= 1'b1;
else if (rx_busy & (bit_count == 4'h9) & ce_1_mid)
rx_busy <= 1'b0;
end
//位计数器
always @ (posedge clock or posedge reset)
begin
if (reset)
bit_count <= 4'h0;
else if (~rx_busy)
bit_count <= 4'h0;
else if (rx_busy & ce_1_mid)
bit_count <= bit_count + 4'h1;
end
// 数据缓冲移位寄存器
always @ (posedge clock or posedge reset)
begin
if (reset)
data_buf <= 8'h0;
else if (rx_busy & ce_1_mid)
data_buf <= {in_sync[1], data_buf[7:1]};//移位寄存器右移,舍去data_buf的最低位,同时in_sync[1]高位写入
end
// data output and flag
always @ (posedge clock or posedge reset)
begin
if (reset)
begin
rx_data <= 8'h0;
new_rx_data <= 1'b0;
end
else if (rx_busy & (bit_count == 4'h8) & ce_1)
begin
rx_data <= data_buf;
new_rx_data <= 1'b1;
end
else
new_rx_data <= 1'b0;
end
//flag
always @ (posedge clock or posedge reset)
begin
if (reset)
new_rx_data <= 1'b0;
else if (rx_busy & (bit_count == 4'h8) & ce_1) //数据接收完成
new_rx_data <= 1'b1;//高电平为空闲状态
else
new_rx_data <= 1'b0;
end
endmodule
参考文献:
【1】opencores
来源:CSDN
作者:菜鸟-求指导
链接:https://blog.csdn.net/qq_43042339/article/details/103818514