UART_RXer.v:
// 2022-1-23 verilog 学习
// 串口接收
`timescale 1ns/10ps
module UART_RXer(
clk,
res,
RX,
data_out,
en_data_out
);
input clk;
input res;
input RX;
output[7:0] data_out; // 接收字节输出
output en_data_out; // 输出使能
reg[7:0] data_out;
reg[7:0] state; // 主状态机
// con用于计算比特宽度 时钟频率24M,1s传4800bits,则1bit占宽5000
reg[12:0] con; // 用于计算比特宽度 24M,24000000/4800=5000=0001 0011 1000 1000,1.5倍5000算8000 = 0001 1111 0100 0000
reg[3:0] con_bits; // 用于计算比特数
reg RX_delay; // RX延时
reg en_data_out;
always@(posedge clk or negedge res)
if(~res)begin
state <= 0; con <=0; con_bits<=0; RX_delay<=0;data_out<=0;
end
else begin
RX_delay <= RX; // RX延时
case(state)
0:// 等空闲
begin
if(con==5000-1)begin // 接收了1bit
con<=0;
end
else begin
con<=con+1; // 数频率
end
if(con==0)begin
if(RX)begin
con_bits <= con_bits+1;
end
else begin
con_bits <= 0;
end
end
if(con_bits == 12)begin
state <=1;
end
end
1://等起始位
begin
en_data_out<=0;
if(~RX & RX_delay)begin
state <= 2;
end
end
2: // 收最低位b0
begin
if(con==7500-1)begin // 1.5个bit
con <= 0;
data_out[0] <= RX; // 第0位
state <= 3;
end
else begin
con <= con+1;
end
end
3: // 收b1
begin
en_data_out <= 0;
if(con==5000-1)begin // 1个bit
con <= 0;
data_out[1] <= RX; //
state <= 4;
end
else begin
con <= con+1;
end
end
4: // 收b2
begin
if(con==5000-1)begin
con <= 0;
data_out[2] <= RX; //
state <= 5;
end
else begin
con <= con+1;
end
end
5: // 收b3
begin
if(con==5000-1)begin
con <= 0;
data_out[3] <= RX; //
state <= 6;
end
else begin
con <= con+1;
end
end
6: // 收b4
begin
if(con==5000-1)begin //
con <= 0;
data_out[4] <= RX; //
state <= 7;
end
else begin
con <= con+1;
end
end
7: // 收b5
begin
if(con==5000-1)begin
con <= 0;
data_out[5] <= RX; //
state <= 8;
end
else begin
con <= con+1;
end
end
8: // 收b6
begin
if(con==5000-1)begin
con <= 0;
data_out[6] <= RX; //
state <= 9;
end
else begin
con <= con+1;
end
end
9: // 收b7
begin
if(con==5000-1)begin
con <= 0;
data_out[7] <= RX; //
state <= 10;
end
else begin
con <= con+1;
end
end
10: // 结束位 产生使能脉冲
begin
en_data_out <= 1;
state <= 1;
end
default: // 万一case>10
begin
state <= 0;
con <= 0;
con_bits <= 0;
en_data_out <= 0;
end
endcase
end
endmodule
// testbench 测试台
module UART_RXer_tb;
reg clk,res;
wire RX; // 已经预设好,不需要变化
wire[7:0] data_out;
wire en_data_out;
reg[25:0] RX_send; // 里面装有串口字节发送数据
assign RX = RX_send[0]; // 连接RX
reg[12:0] con;
// 同名例化 reg变量命名和UART_RXer UART_RXer();块中变量命名相同,则块中不用.clk(clk)
// 异名例化 reg变量命名和UART_RXer UART_RXer();块中变量命名不同,则块中不用.clk(reg/wire中命名)
UART_RXer UART_RXer(
clk,
res,
RX,
data_out,
en_data_out
);
// 初值
initial begin
clk<=0;res<=0;con<=0;RX_send<={1'b1,8'haa,1'b0,16'hffff}; //结束位,字节,起始位,空闲(往右输出)
#17 res<=1;
#4000000 $stop;
end
always #5 clk = ~clk;
always@(posedge clk)begin
if(con==5000-1)begin
con <= 0;
end
else begin
con <= con + 1;
end
if(con==0)begin
RX_send[24:0] <= RX_send[25:1]; // 右移
RX_send[25] <= RX_send[0]; // 循环右移
end
end
endmodule
16’hffff:16位的十六进制,f:16,即1111
8’haa:16位的十六进制 a:10,即1010
1’b0:1位二进制,即0
1’b1:1位二进制,即1
{1’b1, 8’haa, 1’b0, 16’hffff}:1_1010_1010_0_1111_1111_1111_1111
空闲12位以上,识别到空闲:1111_1111_1111_1111,识别到第12个1时,开始等待起始位;
… …
第15个1:RX=1,RX_delay=1(等于上一个时刻的RX);
第16个1:RX=1,RX_delay=1(等于上一个时刻的RX);
RX=1’b0时刻:RX=0,RX_delay=1(等于上一个时刻的RX)。此时 ~RX & RX_delay = 1&1 = 1,识别到起始位,转状态2;
状态2:等待1.5个bit (时钟周期为7500),开始接收b[0];
… …