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

Posted 笑着刻印在那一张泛黄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于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:

 

 1 module detect_module(
 2     CLK,RSTn,
 3     RX_Pin_in,
 4     H2L_Sig
 5     );
 6      input CLK,RSTn;
 7      input RX_Pin_in;
 8      output H2L_Sig;
 9      
10      /**********************************/
11      reg RX_r1;
12      reg RX_r2;
13      
14      always @(posedge CLK or negedge RSTn)
15      begin
16         if(!RSTn)
17         begin
18             RX_r1<=1\'b1;
19             RX_r2<=1\'b1;
20         end
21         else 
22         begin
23             RX_r1<=RX_Pin_in;
24             RX_r2<=RX_r1;
25         end
26      end
27      /*********************************/
28      
29      assign H2L_Sig=RX_r2&(!RX_r1);
30      
31 
32 
33 endmodule

 

rx_bps_module:

 

 1 module rx_bps_module #(parameter Baud=9600)(
 2     CLK,RSTn,
 3     Count_Sig,
 4     BPS_CLK
 5     );
 6     input CLK;
 7     input RSTn;
 8     input Count_Sig;
 9     output BPS_CLK;
10     
11     /***************************/
12     localparam Baud_Div=50_000_000/Baud-1;
13     localparam Baud_Div2=Baud_Div/2;
14     
15     reg[15:0] Count_BPS;
16     /*************************/
17     always @(posedge CLK or negedge RSTn)
18     begin
19         if(!RSTn)
20             Count_BPS<=16\'d0;
21         else if(Count_BPS==Baud_Div)
22             Count_BPS<=16\'d0;
23         else if(Count_Sig)
24             Count_BPS<=Count_BPS+1;
25         else Count_BPS<=16\'d0;
26     end
27     /************************/
28     assign BPS_CLK=(Count_BPS==Baud_Div2)?1\'b1:1\'b0;
29 endmodule

 

rx_control_module:

 

 1 module rx_control_module(
 2     CLK,RSTn,
 3     H2L_Sig,BPS_CLK,RX_Pin_in,
 4     Count_Sig,RX_En_Sig,RX_Done_Sig,RX_Data
 5     );
 6      
 7      input CLK,RSTn;
 8      input H2L_Sig,BPS_CLK,RX_En_Sig,RX_Pin_in;
 9      output Count_Sig,RX_Done_Sig;
10      output [7:0] RX_Data;
11      
12      reg[3:0] i;
13      reg isCount;
14      reg isDone;
15      reg [7:0] rData;
16      /********************************************/
17      always @(posedge CLK or negedge RSTn)
18      begin
19         if(!RSTn)
20         begin
21             i<=4\'d0;
22             isCount<=1\'b0;
23             isDone<=1\'b0;
24             rData<=8\'d0;
25         end
26         else if(RX_En_Sig)
27         begin
28             case(i)
29             4\'d0:if(H2L_Sig) begin i<=i+1\'b1;isCount<=1\'b1; end   //接收到下降沿开始启动波特率计数
30             4\'d1:if(BPS_CLK) begin i<=i+1\'b1; end                 //起始位
31             4\'d2,4\'d3,4\'d4,4\'d5,4\'d6,4\'d7,4\'d8,4\'d9:
32             if(BPS_CLK) begin rData[i-2]<=RX_Pin_in;i<=i+1\'b1;end  //数据位
33             4\'d10:if(BPS_CLK) begin i<=i+1\'b1; end                 //校验位
34             4\'d11:if(BPS_CLK) begin i<=i+1\'b1; end                 //停止位
35             4\'d12:if(BPS_CLK) begin i<=i+1\'b1;isDone<=1\'b1;isCount<=1\'b0; end       //一个时钟脉冲的 isDone 信号 
36             4\'d13:begin i<=1\'b0;isDone<=1\'b0; end
37             endcase
38         end
39      
40      end
41      
42      /********************************************/
43      assign Count_Sig=isCount;
44      assign RX_Done_Sig=isDone;
45      assign RX_Data=rData;
46 
47 
48 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 [7:0] 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:

 

 1 module rx2fifo_module(
 2     CLK,RSTn,
 3     RX_Done_Sig,RX_En_Sig,RX_Data,
 4     Write_Req_Sig,FIFO_Write_Data,Full_Sig
 5     );
 6      input CLK,RSTn;
 7      input RX_Done_Sig;
 8      output RX_En_Sig;
 9      input [7:0] RX_Data;
10      input Full_Sig;
11      output Write_Req_Sig;
12      output [7:0] FIFO_Write_Data;
13      
14      reg isRx;
15      reg isWrite;
16      reg [2:0] i;
17      always @(posedge CLK or negedge RSTn)
18      begin
19         if(!RSTn)
20         begin
21             isRx<=1\'b0;
22             isWrite<=1\'b0;
23             i<=3\'d0;
24         end
25         else 
26         case(i)
27         3\'d0:if(RX_Done_Sig) begin i<=i+1\'b1;isRx<=1\'b0; end
28                 else isRx<=1\'b1;
29         3\'d1:if(!Full_Sig) begin isWrite<=1\'b1;i<=i+1\'b1;end
30         3\'d2:begin isWrite<=1\'b0;i<=3\'d0;end 
31         endcase
32      
33      end
34      
35      assign FIFO_Write_Data=RX_Data;
36      assign RX_En_Sig=isRx;
37      assign Write_Req_Sig=isWrite;
38 
39 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 [7:0] FIFO_Read_Data;
     
    wire RX_Done_Sig;
    wire [7:0]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 [7:0]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 [7:0] FIFO_Read_Data;
     input Empty_Sig;
     output [3:0]Led;
     
     /*******************************************/
     localparam T1S=50_000_000-1;
     reg[31:0] Count_1s;
     always @(posedge CLK or negedge RSTn)
     begin
        if(!RSTn) Count_1s<=32\'d0;
        else if(Count_1s==T1S) Count_1s<=32\'d0;
        else if(isCount) Count_1s<=Count_1s+1\'b1;
        else Count_1s<=32\'d0;
     end
     /*******************************************/
     reg isRead;
     reg [2:0]i;
     reg isCount;
     always @(posedge CLK or negedge RSTn)
     begin
        if(!RSTn)
        begin
            isRead<=1\'b0;
            i<=3\'d0;
            isCount<=1\'b0;
        end
        else 
        case(i)
        3\'d0:if(Count_1s==T1S) begin isCount<=1\'b0;i<=i+1\'b1; end
            else isCount<=1\'b1;
        3\'d1:if(!Empty_Sig) begin isRead<=1\'b1; i<=i+1\'b1;end
        3\'d2:begin  isRead<=1\'b0;i<=3\'d0; end
        endcase
     end
     /*************************************************/
     assign Read_Req_Sig=isRead;
     assign Led=FIFO_Read_Data[3:0];


endmodule

 

rx_interface_top:

 

 1 module rx_interface_top(
 2     CLK,RSTn,RX_Pin_in,
 3     Led
 4     );
 5      input RX_Pin_in;
 6      input CLK,RSTn;
 7      output [3:0]Led;
 8      
 9      wire Read_Req_Sig;
10      wire Empty_Sig;
11      wire[7:0] FIFO_Read_Data;
12     rx_interface U0 (
13     .CLK(CLK), 
14     .RSTn(RSTn), 
15     .RX_Pin_in(RX_Pin_in), 
16     .Read_Req_Sig(Read_Req_Sig), 
17     .Empty_Sig(Empty_Sig), 
18     .FIFO_Read_Data(FIFO_Read_Data)
19 );
20     rx_interface_control U1 (
21         .CLK(CLK), 
22         .RSTn(RSTn), 
23         .Read_Req_Sig(Read_Req_Sig), 
24         .FIFO_Read_Data(FIFO_Read_Data), 
25         .Empty_Sig(Empty_Sig), 
26         .Led(Led)
27     );
28 
29 
30 endmodule

 

 

三、硬件部分

 黑金SPARTAN-6开发板

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

 

以上是关于基于Verilog的带FIFO输出缓冲的串口接收接口封装的主要内容,如果未能解决你的问题,请参考以下文章

串口使用和CSerial类

13.串口通讯的高级方式

Linux fifo 缓冲采坑

DSP之通信之异步串口

verilog常考面试题之同步FIFO设计(给定位宽和深度)

verilog常考面试题之同步FIFO设计(给定位宽和深度)