基于Verilog的带FIFO输出缓冲的串口接收接口封装

时间:2021-11-26 14:38:43

一、模块框图及基本思路

基于Verilog的带FIFO输出缓冲的串口接收接口封装

rx_module:串口接收的核心模块,详细介绍请见“基于Verilog的串口接收实验”

rx2fifo_module:rx_module与rx_fifo之间的控制模块,其功能是不断接收并将数据写入rx_fifo

rx_interface:串口接收接口封装,也就是前两个模块的组合

rx_interface_control:串口接收接口控制模块,每隔1s读取一次串口rx_fifo,并将数据的低四位用Led显示出来

rx_interface_top:串口接收接口顶层模块

二、软件部分

detect_module:

 module detect_module(
CLK,RSTn,
RX_Pin_in,
H2L_Sig
);
input CLK,RSTn;
input RX_Pin_in;
output H2L_Sig; /**********************************/
reg RX_r1;
reg RX_r2; always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
begin
RX_r1<='b1;
RX_r2<='b1;
end
else
begin
RX_r1<=RX_Pin_in;
RX_r2<=RX_r1;
end
end
/*********************************/ assign H2L_Sig=RX_r2&(!RX_r1); endmodule

rx_bps_module:

 module rx_bps_module #(parameter Baud=)(
CLK,RSTn,
Count_Sig,
BPS_CLK
);
input CLK;
input RSTn;
input Count_Sig;
output BPS_CLK; /***************************/
localparam Baud_Div=50_000_000/Baud-;
localparam Baud_Div2=Baud_Div/; reg[:] Count_BPS;
/*************************/
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
Count_BPS<='d0;
else if(Count_BPS==Baud_Div)
Count_BPS<='d0;
else if(Count_Sig)
Count_BPS<=Count_BPS+;
else Count_BPS<='d0;
end
/************************/
assign BPS_CLK=(Count_BPS==Baud_Div2)?'b1:1'b0;
endmodule

rx_control_module:

 module rx_control_module(
CLK,RSTn,
H2L_Sig,BPS_CLK,RX_Pin_in,
Count_Sig,RX_En_Sig,RX_Done_Sig,RX_Data
); input CLK,RSTn;
input H2L_Sig,BPS_CLK,RX_En_Sig,RX_Pin_in;
output Count_Sig,RX_Done_Sig;
output [:] RX_Data; reg[:] i;
reg isCount;
reg isDone;
reg [:] rData;
/********************************************/
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
begin
i<='d0;
isCount<='b0;
isDone<='b0;
rData<='d0;
end
else if(RX_En_Sig)
begin
case(i)
'd0:if(H2L_Sig) begin i<=i+1'b1;isCount<='b1; end //接收到下降沿开始启动波特率计数
'd1:if(BPS_CLK) begin i<=i+1'b1; end //起始位
'd2,4'd3,'d4,4'd5,'d6,4'd7,'d8,4'd9:
if(BPS_CLK) begin rData[i-]<=RX_Pin_in;i<=i+'b1;end //数据位
'd10:if(BPS_CLK) begin i<=i+1'b1; end //校验位
'd11:if(BPS_CLK) begin i<=i+1'b1; end //停止位
'd12:if(BPS_CLK) begin i<=i+1'b1;isDone<='b1;isCount<=1'b0; end //一个时钟脉冲的 isDone 信号
'd13:begin i<=1'b0;isDone<='b0; end
endcase
end end /********************************************/
assign Count_Sig=isCount;
assign RX_Done_Sig=isDone;
assign RX_Data=rData; endmodule

rx_module:

module rx_module(
CLK,RSTn,
RX_Pin_in,RX_Done_Sig,RX_Data,RX_En_Sig
); input CLK,RSTn;
input RX_Pin_in,RX_En_Sig;
output RX_Done_Sig;
output [:] RX_Data; wire Count_Sig;
wire BPS_CLK;
wire H2L_Sig; rx_bps_module U0(
.CLK(CLK),.RSTn(RSTn),
.Count_Sig(Count_Sig),
.BPS_CLK(BPS_CLK)
); detect_module U1(
.CLK(CLK),.RSTn(RSTn),
.RX_Pin_in(RX_Pin_in),
.H2L_Sig(H2L_Sig)
); rx_control_module U2(
.CLK(CLK),.RSTn(RSTn),
.H2L_Sig(H2L_Sig),.BPS_CLK(BPS_CLK),.RX_Pin_in(RX_Pin_in),
.Count_Sig(Count_Sig),.RX_En_Sig(RX_En_Sig),.RX_Done_Sig(RX_Done_Sig),.RX_Data(RX_Data)
); endmodule

rx2fifo_module:

 module rx2fifo_module(
CLK,RSTn,
RX_Done_Sig,RX_En_Sig,RX_Data,
Write_Req_Sig,FIFO_Write_Data,Full_Sig
);
input CLK,RSTn;
input RX_Done_Sig;
output RX_En_Sig;
input [:] RX_Data;
input Full_Sig;
output Write_Req_Sig;
output [:] FIFO_Write_Data; reg isRx;
reg isWrite;
reg [:] i;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
begin
isRx<='b0;
isWrite<='b0;
i<='d0;
end
else
case(i)
'd0:if(RX_Done_Sig) begin i<=i+1'b1;isRx<='b0; end
else isRx<='b1;
'd1:if(!Full_Sig) begin isWrite<=1'b1;i<=i+'b1;end
'd2:begin isWrite<=1'b0;i<='d0;end
endcase end assign FIFO_Write_Data=RX_Data;
assign RX_En_Sig=isRx;
assign Write_Req_Sig=isWrite; endmodule

rx_interface:

module rx_interface(
CLK,RSTn,
RX_Pin_in,
Read_Req_Sig,Empty_Sig,FIFO_Read_Data
);
input CLK,RSTn;
input RX_Pin_in;
input Read_Req_Sig;
output Empty_Sig;
output [:] FIFO_Read_Data; wire RX_Done_Sig;
wire [:]RX_Data;
wire RX_En_Sig;
rx_module U0 (
.CLK(CLK),
.RSTn(RSTn),
.RX_Pin_in(RX_Pin_in),
.RX_Done_Sig(RX_Done_Sig),
.RX_Data(RX_Data),
.RX_En_Sig(RX_En_Sig)
); wire Write_Req_Sig;
wire Full_Sig;
wire [:]FIFO_Write_Data;
rx2fifo_module U1 (
.CLK(CLK),
.RSTn(RSTn),
.RX_Done_Sig(RX_Done_Sig),
.RX_En_Sig(RX_En_Sig),
.RX_Data(RX_Data),
.Write_Req_Sig(Write_Req_Sig),
.FIFO_Write_Data(FIFO_Write_Data),
.Full_Sig(Full_Sig)
);
rx_fifo U2 (
.clk(CLK), // input clk
.rst(!RSTn), // input rst
.din(FIFO_Write_Data), // input [7 : 0] din
.wr_en(Write_Req_Sig), // input wr_en
.rd_en(Read_Req_Sig), // input rd_en
.dout(FIFO_Read_Data), // output [7 : 0] dout
.full(Full_Sig), // output full
.empty(Empty_Sig) // output empty
); endmodule

rx_interface_control:

module rx_interface_control(
CLK,RSTn,
Read_Req_Sig,FIFO_Read_Data,Empty_Sig,
Led
);
input CLK,RSTn;
output Read_Req_Sig;
input [:] FIFO_Read_Data;
input Empty_Sig;
output [:]Led; /*******************************************/
localparam T1S=50_000_000-;
reg[:] Count_1s;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn) Count_1s<='d0;
else if(Count_1s==T1S) Count_1s<='d0;
else if(isCount) Count_1s<=Count_1s+'b1;
else Count_1s<='d0;
end
/*******************************************/
reg isRead;
reg [:]i;
reg isCount;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
begin
isRead<='b0;
i<='d0;
isCount<='b0;
end
else
case(i)
'd0:if(Count_1s==T1S) begin isCount<=1'b0;i<=i+'b1; end
else isCount<='b1;
'd1:if(!Empty_Sig) begin isRead<=1'b1; i<=i+'b1;end
'd2:begin isRead<=1'b0;i<='d0; end
endcase
end
/*************************************************/
assign Read_Req_Sig=isRead;
assign Led=FIFO_Read_Data[:]; endmodule

rx_interface_top:

 module rx_interface_top(
CLK,RSTn,RX_Pin_in,
Led
);
input RX_Pin_in;
input CLK,RSTn;
output [:]Led; wire Read_Req_Sig;
wire Empty_Sig;
wire[:] FIFO_Read_Data;
rx_interface U0 (
.CLK(CLK),
.RSTn(RSTn),
.RX_Pin_in(RX_Pin_in),
.Read_Req_Sig(Read_Req_Sig),
.Empty_Sig(Empty_Sig),
.FIFO_Read_Data(FIFO_Read_Data)
);
rx_interface_control U1 (
.CLK(CLK),
.RSTn(RSTn),
.Read_Req_Sig(Read_Req_Sig),
.FIFO_Read_Data(FIFO_Read_Data),
.Empty_Sig(Empty_Sig),
.Led(Led)
); endmodule

三、硬件部分

黑金SPARTAN-6开发板

 NET "CLK" LOC = T8;
NET "RSTn" LOC = L3;
NET "RX_Pin_in" LOC = C11;
NET "Led[0]" LOC = P4;
NET "Led[1]" LOC = N5;
NET "Led[2]" LOC = P5;
NET "Led[3]" LOC = M6;