在我们实现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作为 顶层模块的输入信号。仿真的工程狂徒如下所示。
波形: