基于A7的DDR3 SDRAM IP仲裁模块

在我们实现DDR3控制器的IP核的读和写之后我们会发现,读和写是共用同一段命令线的,因此读/写需要分时的使用IP核中的命令总线,具体的方法如图所示。

如上图所示,我们可以分时的将A7_wr_ctrl和A7_rd_ctrl模块的app_cmd信号传输给IP核的app_cmd信号。对于A7_wr_ctrl和A7_rd_ctrl模块的app_addr信号,我们可以在不使用时将其置为0,这样我们将A7_wr_ctrl和A7_rd_ctrl模块的app_addr信号进行按位或,结果即为IP核的app_addr。同理,IP核的app_en也可以通过A7_wr_ctrl和A7_rd_ctrl模块的app_en按位或的得到。

 代码如下:

1 assign app_en = app_rd_en | app_wr_en                            ;     
2 assign app_addr = app_rd_addr | app_wr_addr                      ;
3 assign app_cmd = (app_wr_en == 1'b1) ? app_wr_cmd : app_rd_cmd   ;

综上所述,

如上所示,我们完成了读和写模块与IP核的交互,但是加入读、写的启动信号同时产生,将会造成app_addr和app_en同时有效,上述的按位或的方式将会失效,因此我们不能让读/写启动信号同时产生,为了解决这个问题,我们可以加一个仲裁器来控制产生读、写启动信号,框图如下。

 为了完成上图所示的仲裁器,我们可以设定一个状态机,当复位结束后,可以直接进入到仲裁状态,在仲裁状态等待读、写请求,当某一个请求到来,即进入到对应的状态执行相应的操作,并且只有在仲裁状态时读、写不会冲突。

 

 代码如下:

  1 //**************************************************************************
  2 // *** 名称 : arbit.v
  3 // *** 作迿 : tedyma
  4 // *** 博客 : https://www.cnblogs.com/tedymafpga/
  5 // *** 日期 : 2019-08-10
  6 // *** 描述 : DDR3仲裁模块
  7 //**************************************************************************
  8 module arbit
  9 //========================< 端口 >==========================================
 10 (
 11 //system ----------------------------------------
 12 input   wire                 sclk                , //时钟_50Mhz
 13 input   wire                 rst                 , //复位,低电平有效
 14 //input -----------------------------------------
 15 input   wire                    wr_req           , //输入in
 16 input   wire                    rd_req           , 
 17 input     wire                wr_end             ,
 18 input     wire                rd_end             ,
 19 //output ----------------------------------------
 20 output  wire                wr_cmd_start         , //输出out
 21 output  wire                rd_cmd_start
 22 );
 23 //========================< 信号 >==========================================
 24 reg   [3:0]                 state                ;
 25 reg                            wr_flag           ;
 26 reg                            rd_flag           ;
 27 reg                            wr_cmd_start_r    ;
 28 reg                            rd_cmd_start_r    ;
 29 //==========================================================================
 30 //==宏定乿    
 31 //==========================================================================
 32 parameter     IDLE    =    4'b0001               ;                
 33 parameter     ARBIT    =    4'b0010              ;        
 34 parameter     WR        =    4'b0100             ;        
 35 parameter     RD        =    4'b1000             ;    
 36 //==========================================================================
 37 //==    输出
 38 //==========================================================================
 39 assign wr_cmd_start = wr_cmd_start_r             ;
 40 assign rd_cmd_start = rd_cmd_start_r             ;
 41 
 42     
 43 //==========================================================================
 44 //==    状濁机
 45 //==========================================================================
 46 always @(posedge sclk) begin
 47     if(rst) begin
 48         state <= IDLE;
 49     end
 50     else begin
 51         case(state)
 52             IDLE:    state <= ARBIT;
 53             ARBIT:if(wr_req == 1'b1 )begin
 54                 state <= WR;
 55             end
 56             else if(rd_req == 1'b1)begin
 57                 state <= RD;
 58             end
 59             WR:    if(state == WR && wr_end == 1'b1)begin
 60                 state <= ARBIT;
 61             end
 62             RD:if(state == RD && rd_end == 1'b1)begin
 63                 state <= ARBIT;
 64             end
 65             default:state <= IDLE;
 66         endcase
 67     end
 68 end
 69 //-----------------------------------------------
 70 always @(posedge sclk) begin
 71     if(rst) begin
 72         wr_flag <= 1'b0;
 73     end
 74     else if(state == WR && wr_flag == 1'b1)begin
 75         wr_flag <= 1'b0;
 76     end
 77     else if(wr_req == 1'b1)begin
 78         wr_flag <= 1'b1;
 79     end
 80 end
 81 //-----------------------------------------------
 82 always @(posedge sclk) begin
 83     if(rst) begin
 84         rd_flag <= 1'b0;
 85     end
 86     else if(state == RD && rd_flag == 1'b1)begin
 87         rd_flag <= 1'b0;
 88     end
 89     else if(rd_req == 1'b1)begin
 90         rd_flag <= 1'b1;
 91     end
 92 end
 93 //==========================================================================
 94 //==    wr_cmd_start_r
 95 //==========================================================================
 96 always @(posedge sclk)begin 
 97     if(rst) begin
 98         wr_cmd_start_r <= 1'b0;
 99     end
100     else if(wr_flag == 1'b1 && state == WR)begin
101         wr_cmd_start_r <= 1'b1;
102     end
103     else begin
104         wr_cmd_start_r <= 1'b0;
105     end
106 end
107 //==========================================================================
108 //==    rd_cmd_start_r
109 //==========================================================================
110 always @(posedge sclk) begin
111     if(rst) begin
112         rd_cmd_start_r <= 1'b0;
113     end
114     else if(rd_flag == 1'b1 && state == RD)begin
115         rd_cmd_start_r <= 1'b1;
116     end
117     else begin
118         rd_cmd_start_r <= 1'b0;
119     end
120 end
121 
122 endmodule

仿真

将wr_req和rd_req作为 顶层模块的输入信号。仿真的工程狂徒如下所示。

波形:

猜你喜欢

转载自www.cnblogs.com/tedymafpga/p/11794177.html