論理回路デザイン
ArchiTek home page
コーディング1

コード(sdcCntl RTL)

/* **************************** 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 ▲