論理回路デザイン |
|
/* **************************** MODULE PREAMBLE ******************************** Copyright (c) 2012, ArchiTek This document constitutes confidential and proprietary information of ArchiTek. All rights reserved. */ // ***************************** MODULE HEADER ********************************* module sdcCntl ( iReq, iGnt, iRxw, iAddr, pReq, pGnt, pAddr, wrPush, rdPush, cs_n, ras_n, cas_n, we_n, addr, ba, reg_pCOM, reg_pACCW, reg_pACCR, reg_pFAW, reg_pRRD, reg_dTWR, reg_dTRW, reg_dWL, reg_dRL, rdWL, rdRL, clk, reset_n ); // ************************* PARAMETER DECLARATIONS **************************** parameter ROWS = 5'h00; // Row Address Start Bit parameter IDLE = 5'h00, // Idle REDY = 5'h01, // Ready to PREP PREP = 5'h02, // Prepare to PREV PREV = 5'h03, // Previous to DIRC DIRC = 5'h08, // Direct Command ABRT = 5'h09, // Abort WACT = 5'h10, // Write Activate WVIR = 5'h11, // Write Activate Virtual WNUL = 5'h12, // Write Activate Null WEND = 5'h13, // Write Activate End WRAP = 5'h14, // Write Command Precharge WRSQ = 5'h15, // Write Command Sequential WRNL = 5'h16, // Write Command Null WTHR = 5'h17, // Write Thru (Activate) RACT = 5'h18, // Read Activate RVIR = 5'h19, // Read Activate Virtual RNUL = 5'h1a, // Read Activate Null REND = 5'h1b, // Read Activate End RDAP = 5'h1c, // Read Command Precharge RDSQ = 5'h1d, // Read Command Sequential RDNL = 5'h1e, // Read Command Null RTHR = 5'h1f; // Read Thru (Activate) // ******************************* REFERENCE *********************************** // SDRAM ADDRESS FIELD // [16bit DDR] =================== // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 B2 B1 B0 // +======================================================+==========+ // DIRECT | 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 | 14 13 12 | // +======================================================+==========+ // ACT | ROWS +F +E +D +C +B +A +9 +8 +7 +6 +5 +4 +3 +2 +1 +0 | 6 5 4 | // +------------------------------------------------------+----------+ // COM | 17 16 15 H 14 AP 13 12 11 10 9 8 7 L L L | 6 5 4 | // +======================================================+==========+ // // pAddr[8]→ras_n、pAddr[9]→cas_n、pAddr[10]→we_nに加えてpAddr[0]→cs_nをマッピング // 通常アクセスのActivateで、iAddr[ROWS+15:ROWS]→addr[15:0]、iAddr[6:4]→ba[2:0]にマッピング // 通常アクセスのR/WでiAddr[17:15]'1'[13:7]'000'→addr[15:0]にマッピング // ・DDR側でaddr[15:14]は使用しない // *************************** I/O DECLARATIONS ******************************** // Normal Master input iReq; output iGnt; input iRxw; input [31:0] iAddr; // Interrupt Master input pReq; output pGnt; input [31:0] pAddr; // Data Path Timing output wrPush; output rdPush; // SDRAM Interface output cs_n; output ras_n; output cas_n; output we_n; output [15:0] addr; output [2:0] ba; // Register Interface input [7:0] reg_pACCW; input [7:0] reg_pACCR; input [7:0] reg_pCOM; input [4:0] reg_pFAW; input [4:0] reg_pRRD; input [4:0] reg_dTWR; input [4:0] reg_dTRW; input [4:0] reg_dWL; input [4:0] reg_dRL; output [4:0] rdWL; output [4:0] rdRL; // Utility input clk; input reset_n; // ************************** LOCAL DECLARATIONS ******************************* // Parameter Latch reg [7:0] rpACCW, rpACCR, rpCOM; reg [31:0] rpFAW, rpRRD; reg [4:0] rdTWR, rdTRW; reg [4:0] rdWL, rdRL; // Status Control reg [4:0] state, stateD; reg setAct, setCom; wire tiReq, tpReq; reg iGnt, pGnt; reg wrPush, rdPush; reg wrPushD, rdPushD; reg [31:0] tmpAddr; // synopsys translate_off reg [31:0] stateName; // synopsys translate_on reg stateWait; wire stateWaitD; reg [4:0] stateCnt; wire [4:0] stateCntD; wire waitInc, cntInc; reg evalOk, wrOk, rdOk; wire evalOkD, wrOkD, rdOkD; // Address Latch reg [31:0] fifoAddr; // Normal Access Bank Count reg [7:0] iRead; reg [7:0] iCnt[0:7], iCntD[0:7]; reg [7:0] iDone; reg [7:0] iTerm, iTermD; reg iAccess; wire iAct; wire iAlloc = iReq & iGnt; // BankアドレスをDDR 16bit版に変更 wire [2:0] iBank = iAddr[6:4]; // Special Access Count reg [7:0] pCnt; wire [7:0] pCntD; reg pDone; reg pAccess; wire pAlloc = pReq & pGnt; // Four Active Window Control reg actOver, actIn; wire [2:0] actFAW, actRRD; reg [31:0] actFIFO; // Output Signals reg statPrev, statIdleAp, statActIn, statWrRdAll, statWrAll; reg cs_n, ras_n, cas_n, we_n; reg [15:0] addr; reg [2:0] ba; wire [15:0] rowAddr, colAddr; // Utlity integer i; // ****************************** MODULE BODY ********************************** // ----------------------------------------------------------------------------- // To Change Parameter always @(posedge clk) if (stateD == IDLE) begin rpACCW <= #1 reg_pACCW - 8'h02; rpACCR <= #1 reg_pACCR - 8'h02; rpCOM <= #1 reg_pCOM - 8'h04; rpFAW <= #1 spFunc(reg_pFAW, 5'h04); rpRRD <= #1 spFunc(reg_pRRD, 5'h04); rdTWR <= #1 rvFunc(reg_dTWR, 5'h04); rdTRW <= #1 rvFunc(reg_dTRW, 5'h04); rdWL <= #1 reg_dWL - 5'h03; rdRL <= #1 reg_dRL; end // ----------------------------------------------------------------------------- // Reduced state machine always @( state or tiReq or iRxw or iAddr or iAccess or tpReq or pAccess or evalOk or wrOk or rdOk or fifoAddr or actOver ) begin stateD = state; iGnt = 1'b0; pGnt = 1'b0; setAct = 1'b0; setCom = 1'b0; wrPushD = 1'b0; rdPushD = 1'b0; tmpAddr = fifoAddr; case (state) IDLE: // idle: setup or ship any command begin // synopsys translate_off stateName = "IDLE"; // synopsys translate_on casex ({actOver, tpReq, tiReq, iRxw, iAccess}) 5'b0010x: begin stateD = WACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end 5'b0011x: begin stateD = RACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end 5'bx1xx0: stateD = PREV; endcase end PREV: // idle: previous to ship direct command begin // synopsys translate_off stateName = "PREV"; // synopsys translate_on stateD = DIRC; setAct = 1'b1; end DIRC: // direct assert for any command begin // synopsys translate_off stateName = "DIRC"; // synopsys translate_on stateD = ABRT; pGnt = 1'b1; end ABRT: // abort begin // synopsys translate_off stateName = "ABRT"; // synopsys translate_on if (!pAccess) stateD = IDLE; end WACT: // activate command for write begin // synopsys translate_off stateName = "WACT"; // synopsys translate_on if (evalOk) begin stateD = WRAP; setCom = 1'b1; wrPushD = 1'b1; end end WRAP: // write command with precharge begin // synopsys translate_off stateName = "WRAP"; // synopsys translate_on casex ({actOver, evalOk, wrOk, tpReq, tiReq, iRxw}) 6'b01x010: begin stateD = WACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end 6'b0x1011: begin stateD = RACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end 6'bxxx1xx, 6'bxx100x: stateD = IDLE; endcase end RACT: // activate command for read begin // synopsys translate_off stateName = "RACT"; // synopsys translate_on if (evalOk) begin stateD = RDAP; setCom = 1'b1; rdPushD = 1'b1; end end RDAP: // read command with precharge begin // synopsys translate_off stateName = "RDAP"; // synopsys translate_on casex ({actOver, evalOk, rdOk, tpReq, tiReq, iRxw}) 6'b01x011: begin stateD = RACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end 6'b0x1010: begin stateD = WACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end 6'bxxx1xx, 6'bxx100x: stateD = IDLE; endcase end endcase end always @(posedge clk or negedge reset_n) if (!reset_n) begin state <= #1 IDLE; evalOk <= #1 1'b0; stateWait <= #1 1'b0; stateCnt <= #1 5'h00; {wrOk, rdOk} <= #1 2'b00; end else begin state <= #1 stateD; evalOk <= #1 evalOkD; stateWait <= #1 stateWaitD; stateCnt <= #1 stateCntD; {wrOk, rdOk} <= #1 {wrOkD, rdOkD}; end assign stateWaitD = (setAct | setCom) ? 1'h0 : stateWait + waitInc; assign stateCntD = setCom ? 5'h00 : stateCnt + {4'd0, cntInc}; assign waitInc = (state != IDLE) & (stateWait != 1'h1); assign cntInc = (state >= WACT) & (!wrOk | !rdOk); assign evalOkD = (stateWaitD == 1'h1); assign wrOkD = (stateCntD > rdTWR); assign rdOkD = (stateCntD > rdTRW); assign tiReq = iReq & !iAct; assign tpReq = pReq; // ----------------------------------------------------------------------------- // Normal Access Bank Count always @( iCnt[0] or iCnt[1] or iCnt[2] or iCnt[3] or iCnt[4] or iCnt[5] or iCnt[6] or iCnt[7] or iDone or iTerm or iAlloc or iBank ) for (i=0; i<8; i=i+1) if (iDone[i]) begin iCntD[i] = 8'h00; iTermD[i] = 1'b0; end else if (iAlloc & (i[2:0] == iBank)) begin iCntD[i] = 8'h01; iTermD[i] = 1'b1; end else begin iCntD[i] = iCnt[i] + {7'd0, iTerm[i]}; iTermD[i] = iTerm[i]; end always @(posedge clk or negedge reset_n) if (!reset_n) iAccess <= #1 1'b0; else iAccess <= #1 |iTermD; always @(posedge clk or negedge reset_n) if (!reset_n) iRead <= #1 8'h00; else for (i=0; i<8; i=i+1) if (iAlloc & (i[2:0] == iBank)) iRead[i] <= #1 iRxw; always @(posedge clk or negedge reset_n) if (!reset_n) for (i=0; i<8; i=i+1) begin iCnt[i] <= #1 8'h00; iDone[i] <= #1 1'b0; iTerm[i] <= #1 1'b0; end else for (i=0; i<8; i=i+1) begin iCnt[i] <= #1 iCntD[i]; iDone[i] <= #1 (iCnt[i] == (iRead[i] ? rpACCR : rpACCW)); iTerm[i] <= #1 iTermD[i]; end assign iAct = iTerm[iBank]; // ----------------------------------------------------------------------------- // Special Access Count always @(posedge clk or negedge reset_n) if (!reset_n) begin pCnt <= #1 8'h00; pDone <= #1 1'b0; pAccess <= #1 1'b0; end else begin pCnt <= #1 pCntD; pDone <= #1 |pCnt & (pCnt == rpCOM); pAccess <= #1 |pCntD; end assign pCntD = pDone ? 8'h00 : pCnt + {7'd0, pAlloc | pAccess}; // ----------------------------------------------------------------------------- // Address FIFO always @(posedge clk) if (iAlloc) fifoAddr <= #1 iAddr; // ----------------------------------------------------------------------------- // Flags always @(posedge clk or negedge reset_n) if (!reset_n) begin wrPush <= #1 1'b0; rdPush <= #1 1'b0; end else begin wrPush <= #1 wrPushD; rdPush <= #1 rdPushD; end // ----------------------------------------------------------------------------- // Four Active Window Control always @(posedge clk or negedge reset_n) if (!reset_n) begin actOver <= #1 1'b0; actIn <= #1 1'b0; actFIFO <= #1 32'h00000000; end else begin actOver <= #1 (actFAW > 3'h4) | (actRRD > 3'h1); actIn <= #1 (stateD == IDLE) | (stateD == WRAP) | (stateD == RDAP); actFIFO <= #1 {actFIFO[30:0], setAct & actIn}; end assign actFAW = sumFunc(actFIFO & rpFAW); assign actRRD = sumFunc(actFIFO & rpRRD); // ----------------------------------------------------------------------------- // SDRAM One Hot State always @(posedge clk or negedge reset_n) if (!reset_n) begin statPrev <= #1 1'b0; statIdleAp <= #1 1'b1; statActIn <= #1 1'b1; statWrRdAll <= #1 1'b0; statWrAll <= #1 1'b0; end else begin statPrev <= #1 (stateD == PREV); statIdleAp <= #1 (stateD == IDLE) | (stateD == WRAP) | (stateD == RDAP); statActIn <= #1 (stateD == IDLE) | (stateD == WRAP) | (stateD == RDAP) | (stateD == PREV); statWrRdAll <= #1 (stateD >= WACT); statWrAll <= #1 (stateD >= WACT) & (stateD < RACT); end // ----------------------------------------------------------------------------- // SDRAM Command Set // 割り込みアクセス用の最初の式で、cs_n信号にpAddr[0]をアサイン always @(posedge clk or negedge reset_n) if (!reset_n) cs_n <= #1 1'b1; else cs_n <= #1 ~( setAct & statPrev & ~pAddr[0] | setAct & statIdleAp | setCom ); always @(posedge clk or negedge reset_n) if (!reset_n) ras_n <= #1 1'b1; else ras_n <= #1 ~( setAct & statPrev & ~pAddr[8] | setAct & statIdleAp ); always @(posedge clk or negedge reset_n) if (!reset_n) cas_n <= #1 1'b1; else cas_n <= #1 ~( setAct & statPrev & ~pAddr[9] | setCom & statWrRdAll ); always @(posedge clk or negedge reset_n) if (!reset_n) we_n <= #1 1'b1; else we_n <= #1 ~( setAct & statPrev & ~pAddr[10] | setCom & statWrAll ); // ----------------------------------------------------------------------------- // SDRAM Address Set // DDR 16bit版に対応したバンク信号とアドレス信号 always @(posedge clk or negedge reset_n) if (!reset_n) ba <= #1 3'h0; else if (setAct & statActIn) ba <= #1 {3{statPrev}} & pAddr[14:12] | {3{statIdleAp}} & tmpAddr[6:4]; always @(posedge clk or negedge reset_n) if (!reset_n) addr <= #1 16'h0000; else if (setAct & statActIn | setCom) addr <= #1 {16{setAct & statPrev}} & pAddr[31:16] | {16{setAct & statIdleAp}} & rowAddr | {16{setCom}} & colAddr; assign rowAddr = addrRowFunc(tmpAddr, ROWS); assign colAddr = addrColFunc(tmpAddr); // ************************** FUNCTIONS and TASKS ****************************** function [15:0] addrRowFunc; input [31:0] addr; input [4:0] rs; case (rs) 5'h08: addrRowFunc = addr[23:8]; 5'h09: addrRowFunc = addr[24:9]; 5'h0a: addrRowFunc = addr[25:10]; 5'h0b: addrRowFunc = addr[26:11]; 5'h0c: addrRowFunc = addr[27:12]; 5'h0d: addrRowFunc = addr[28:13]; 5'h0e: addrRowFunc = addr[29:14]; 5'h0f: addrRowFunc = addr[30:15]; default: addrRowFunc = addr[31:16]; endcase endfunction // 入力アドレスからColumnアドレスへのマッピング // DDR 16bit版に対応するためのファンクションに変更 function [15:0] addrColFunc; input [31:0] addr; integer i; for (i=0; i<16; i=i+1) if (i < 3) addrColFunc[i] = 1'b0; else if (i < 10) addrColFunc[i] = addr[i+4]; else if (i < 11) // ap addrColFunc[i] = 1'b1; else if (i < 12) addrColFunc[i] = addr[14]; else if (i < 13) // bc addrColFunc[i] = 1'b1; else addrColFunc[i] = addr[i+2]; endfunction function [31:0] spFunc; input [4:0] sp; input [4:0] bias; reg [5:0] tmp; reg [4:0] sft; integer i; begin tmp = {1'd0, sp} - {1'd0, bias}; sft = (~|sp | tmp[5]) ? 5'h00 : tmp[4:0]; for (i=0; i<32; i=i+1) spFunc[i] = (sft < i[4:0]) ? 1'b0 : 1'b1; end endfunction function [4:0] rvFunc; input [4:0] val; input [4:0] bias; reg [5:0] tmp; begin tmp = {1'd0, val} - {1'd0, bias}; rvFunc = tmp[5] ? 5'h00 : tmp[4:0]; end endfunction function [2:0] sumFunc; input [31:0] act; reg [5:0] sum; integer i; begin sum = 6'h00; for (i=0; i<32; i=i+1) sum = sum + {5'd0, act[i]}; sumFunc = sum[2:0]; // Clip since sum <= 4 end endfunction endmodule // *****************************************************************************
回路デザイン > 設計例 [DDR制御(実装)] > コーディング1 次のページ(コーディング2) このページのTOP ▲