如图所示.本串口RX模块包含 RX信号线,时钟Clk、 接收完成标志 rdsig ,数据错误dataerror(奇偶校验),格式错误(停止位)、数据接收结果dataout[7:0]。
基于这样的结构。以下是模块的Verilog实现代码,其中一些变量名有所改变:
UART_RX:
`timescale 1ns / 1ps
//
// Company:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module UART_RX(
input RX, // UART的RX
input clk_div, // 时钟
output reg rx_flag, // 接收完成标志
output reg dataerror, // 数据错误标志
output reg frameerror, // 帧错误
output reg[7:0]data // 接收到的数据
);
//reg[7:0]data;
reg[7:0]cnt;
reg rxbuf,rxfall,receive;
parameter paritymoed = 1'b0;
reg presult,idle;
always@(posedge clk_div) // 下降沿信号
begin
rxbuf <= RX;
rxfall <= rxbuf&(~RX);
end
always@(posedge clk_div)
begin
if(rxfall && (~idle))
begin
receive <= 1'b1;
end
else if(cnt == 8'd168)
receive <= 1'b0;
end
always@(posedge clk_div)
begin
if(receive == 1'b1)
begin
case(cnt)
8'd0:begin // 起始位
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[7:0] <= 8'bz;
end
8'd24:begin // bit 0
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[0] <= RX;
presult <= paritymoed ^ RX;
end
8'd40:begin // bit 1
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[1] <= RX;
presult <= presult ^ RX;
end
8'd56:begin // bit 2
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[2] <= RX;
presult <= presult ^ RX;
end
8'd72:begin // bit 3
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[3] <= RX;
presult <= presult ^ RX;
end
8'd88:begin // bit 4
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[4] <= RX;
presult <= presult ^ RX;
end
8'd104:begin // bit 5
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[5] <= RX;
presult <= presult ^ RX;
end
8'd120:begin // bit 6
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b0;
data[6] <= RX;
presult <= presult ^ RX;
end
8'd136:begin // bit 7
idle <= 1'b1;
cnt <= cnt + 1'b1;
rx_flag <= 1'b1;
data[7] <= RX;
presult <= presult ^ RX;
end
8'd152:begin // bit 校验位
idle <= 1'b1;
cnt <= cnt + 1'b1;
if(presult == RX)
dataerror <= 1'b0;
else
dataerror <= 1'b1;
rx_flag <= 1'b1;
end
8'd168:begin // bit 停止位
idle <= 1'b1;
cnt <= cnt + 1'b1;
if(1'b1 == RX)
frameerror <= 1'b0;
else
frameerror <= 1'b1;
rx_flag <= 1'b1;
end
default: cnt <= cnt + 8'b1;
endcase
end
else
begin
cnt <= 8'b0;
idle <= 1'b0;
rx_flag <= 1'b0;
end
end
endmodule
以下是对应的testbench代码:
RX_tb.V :
`include "UART_RX.v"
module RX_tb;
reg RX,clk_div;
wire rx_flag,dataerror,frameerror;
wire [7:0]data;
// 例化
UART_RX RX_U1(
.RX(RX), // UART的RX
.clk_div(clk_div), // 时钟
.rx_flag(rx_flag), // 接收完成标志
.dataerror(dataerror), // 数据错误标志
.frameerror(frameerror), // 帧错误
.data(data)
);
initial
begin
RX = 1;
clk_div = 1;
forever // 重复产生 RX信号,对模块产生激励
begin
#100;
#10 RX = 0; // 起始位
#16 RX = 1; // bit 0
#16 RX = 0; // bit 1
#16 RX = 1; // bit 2
#16 RX = 0; // bit 3
#16 RX = 1; // bit 4
#16 RX = 0; // bit 5
#16 RX = 1; // bit 6
#16 RX = 0; // bit 7
#16 RX = 1; // bit 校验,这里校验位是1
#16 RX = 1; // bit 停止
end
end
always #0.5 clk_div = ~clk_div;
endmodule
modelsim 仿真结果: