論理回路デザイン |
|
/* **************************** 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 **************************** // Rowアドレスのスタートを定める(上位モジュールで設定) 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 // =================== // 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 | 5 4 3 | // +------------------------------------------------------+----------+ // COM | 16 15 14 H 13 AP 12 11 10 9 8 7 6 L L L | 5 4 3 | // +======================================================+==========+ // // 割り込みアクセス時、pAddr[31:16]→addr[15:0]、pAddr[14:12]→ba[2:0]にマッピング // また、pAddr[8]→ras_n、pAddr[9]→cas_n、pAddr[10]→we_nにマッピング // 通常アクセスのActivateで、iAddr[ROWS+15:ROWS]→addr[15:0]、iAddr[5:3]→ba[2:0]にマッピング // 通常アクセスのR/WでiAddr[16:14]'1'[12:6]'000'→addr[15:0]にマッピング // ・DDR側でaddr[15:13]は使用しない // ・addr[12]は'1'にしてDDR3のBurst Chop機能を使わない // ・addr[10]は'1'にしてAuto Pre-charge機能を使う(ページ機能を実装するとここが変化) // *************************** I/O DECLARATIONS ******************************** // Normal Master // 通常アクセスのRequest信号グループ(ハンドシェークを実施) input iReq; output iGnt; input iRxw; input [31:0] iAddr; // 割り込みアクセスのRequest信号グループ(ハンドシェークを実施) // Interrupt Master input pReq; output pGnt; input [31:0] pAddr; // sdcRdとsdcWrにR/Wコマンド発行タイミングを通知 // Data Path Timing output wrPush; output rdPush; // PHYに接続するDDR信号、簡易版なのでCKEやODTは除かれている // SDRAM Interface output cs_n; output ras_n; output cas_n; output we_n; output [15:0] addr; output [2:0] ba; // 静的なパラメータ群、ステートマシンが停止している時点で取り込み // rdWL, rdRLはsdcWr, sdcRdへパラメータ伝達、一旦ラッチするためこのモジュールで管理 // Register Interface input [7:0] reg_pACCW; // BankごとのWriteアクセス占有間隔(min) input [7:0] reg_pACCR; // BankごとのReadアクセス占有間隔(min) input [7:0] reg_pCOM; // リフレッシュなど特殊コマンドの占有間隔(min) input [4:0] reg_pFAW; // Activateが4つ存在してもよい間隔(max) input [4:0] reg_pRRD; // Activateが2つ存在してもよい間隔(max) input [4:0] reg_dTWR; // Write→Read遷移に必要な間隔(min) input [4:0] reg_dTRW; // Read→Write遷移に必要な間隔(min) input [4:0] reg_dWL; // 正確なWrite Latency input [4:0] reg_dRL; // 正確なRead Latency output [4:0] rdWL; output [4:0] rdRL; // Utility // 単一クロック制御 input clk; input reset_n; // ************************** LOCAL DECLARATIONS ******************************* // Parameter Latch // システムによっては不必要、その場合reg_*をそのまま使用 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; // 使用する状態は8つなので、3bitに圧縮可能 reg setAct, setCom; // Activate, R/Wタイミング wire tiReq, tpReq; // iReq, pReqをフィルタした信号(禁止期間マスク) reg iGnt, pGnt; reg wrPush, rdPush; reg wrPushD, rdPushD; reg [31:0] tmpAddr; // DDRに接続するテンポラリアドレス // synopsys translate_off reg [31:0] stateName; // synopsys translate_on デバッグ用(ASCII) reg stateWait; // 状態遷移指示信号evalOk生成用のカウンター wire stateWaitD; reg [4:0] stateCnt; // 状態遷移指示信号wrOk, rdOk生成用のカウンター wire [4:0] stateCntD; // 通常アクセス時に使用する状態遷移指示信号 wire waitInc, cntInc; reg evalOk, wrOk, rdOk; wire evalOkD, wrOkD, rdOkD; // Address Latch // iAddrを一旦ラッチ、R/Wコマンド発行時に使用 reg [31:0] fifoAddr; // Normal Access Bank Count // 通常アクセス用のバンクごとの禁止区間生成用(ACCW, ACCRから生成) // FF間の論理段数削減のため、ラッチしたタイミング信号iDoneを用意 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; wire [2:0] iBank = iAddr[5:3]; // Special Access Count // 割り込みアクセス用の禁止区間生成用(COMから生成) // FF間の論理段数削減のため、ラッチしたタイミング信号pDoneを用意 reg [7:0] pCnt; wire [7:0] pCntD; reg pDone; reg pAccess; wire pAlloc = pReq & pGnt; // Four Active Window Control // 区間内のActivate数を数えるための変数 reg actOver, actIn; wire [2:0] actFAW, actRRD; reg [31:0] actFIFO; // Output Signals // FF間の論理段数削減のため、状態をラッチしたタイミング信号(One hot)を用意 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 // 状態がIDLEならパラメータをラッチ、stateDを使用するのは前もって準備するため // 引き算しているのは、ステートマシンの遷移時間や終了判定の時間を考慮してのもの // spFuncは特殊カウンターactFIFOで使用するマスクを生成 // rvFuncは0以下になる可能性のある変数に対し、0以下は0になるよう補正 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'h04; rdRL <= #1 reg_dRL; end // ----------------------------------------------------------------------------- // Reduced state machine // メインのステートマシン // 状態を表すstate、マスターへのgnt、コマンド発行タイミング、DDRへのアドレスを生成 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 // 最初にデフォルト値を設定、これを外れる条件のみcase()内で更新 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: // idle: setup or ship any command begin // synopsys translate_off // 波形観測で状態名をASCII表示、合成時時は自動的にスキップ stateName = "IDLE"; // synopsys translate_on casex ({actOver, tpReq, tiReq, iRxw, iAccess}) // WriteアクセスでActivateへ、iAccessは既にマスクされているため見ない // このタイミングでOKならiGntをアサート // Activateコマンドのタイミングを生成、iAddrをそのままaddr信号へ 5'b0010x: begin stateD = WACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end // ReadアクセスでActivateへ、iAccessは既にマスクされているため見ない // このタイミングでOKならiGntをアサート // Activateコマンドのタイミングを生成、iAddrをそのままaddr信号へ 5'b0011x: begin stateD = RACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end // 割り込みアクセス、上記に優先して遷移 // 通常アクセス(iAccess)に関するスケジュールが全て消えるまで待機 5'bx1xx0: stateD = PREV; endcase end // PREVは割り込みアクセスのコマンド発行の前段階(IDLEと同じ) // One hotを作るために定義 PREV: // idle: previous to ship direct command begin // synopsys translate_off stateName = "PREV"; // synopsys translate_on stateD = DIRC; setAct = 1'b1; end // DIRCは任意コマンドの発行タイミング、ラッチアドレスをaddr信号へ // このタイミングでpGntをアサート DIRC: // direct assert for any command begin // synopsys translate_off stateName = "DIRC"; // synopsys translate_on stateD = ABRT; pGnt = 1'b1; end // ABRTは任意コマンドのACタイミング(COM)を満足するための待機状態 ABRT: // abort begin // synopsys translate_off stateName = "ABRT"; // synopsys translate_on // pReq & pGntで開始したカウントがCOMに未到達なら待機 if (!pAccess) stateD = IDLE; end // WACTはActivateコマンドの発行タイミング、Writeの区別はWRAPに遷移するため WACT: // activate command for write begin // synopsys translate_off stateName = "WACT"; // synopsys translate_on // evalOkを見て1サイクルNOPが挿入された後かをチェック // Writeコマンドのタイミングを生成、ラッチアドレスをaddr信号へ if (evalOk) begin stateD = WRAP; setCom = 1'b1; wrPushD = 1'b1; end end // WRAPはWriteコマンドの発行タイミング、IDLEと同じく続くiReqをチェック WRAP: // write command with precharge begin // synopsys translate_off stateName = "WRAP"; // synopsys translate_on casex ({actOver, evalOk, wrOk, tpReq, tiReq, iRxw}) // Writeアクセスが続き、actOver(RRD/FAW)とevalOkを満足すればWACTへ // Write→WriteなのでwrOkは見ない 6'b01x010: begin stateD = WACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end // Readアクセスに変わり、actOver(RRD/FAW)とwrOkを満足すればRACTへ // wrOk成立時はevalOkも成立するので見ない 6'b0x1011: begin stateD = RACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end // 割り込みアクセスがある場合は強制的にIDLEへ、IDLEでPREVに導かれる // また、アクセスがなく全てのACタイミングが満たされればIDLEへ 6'bxxx1xx, 6'bxx100x: stateD = IDLE; endcase end // RACTはActivateコマンドの発行タイミング、Readの区別はRDAPに遷移するため RACT: // activate command for read begin // synopsys translate_off stateName = "RACT"; // synopsys translate_on // evalOkを見て1サイクルNOPが挿入された後かをチェック // Readコマンドのタイミングを生成、ラッチアドレスをaddr信号へ if (evalOk) begin stateD = RDAP; setCom = 1'b1; rdPushD = 1'b1; end end // RDAPはReadコマンドの発行タイミング、IDLEと同じく続くiReqをチェック RDAP: // read command with precharge begin // synopsys translate_off stateName = "RDAP"; // synopsys translate_on casex ({actOver, evalOk, rdOk, tpReq, tiReq, iRxw}) 6'b01x011: begin // Readアクセスが続き、actOver(RRD/FAW)とevalOkを満足すればRACTへ // Read→ReadなのでrdOkは見ない stateD = RACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end // Writeアクセスに変わり、actOver(RRD/FAW)とrdOkを満足すればWACTへ // rdOk成立時はevalOkも成立するので見ない 6'b0x1010: begin stateD = WACT; iGnt = 1'b1; setAct = 1'b1; tmpAddr = iAddr; end // 割り込みアクセスがある場合は強制的にIDLEへ、IDLEでPREVに導かれる // また、アクセスがなく全てのACタイミングが満たされればIDLEへ 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 // コマンド間にNOPを挿入するため、任意コマンドの発行でクリアし自動インクリメントするカウンター assign stateWaitD = (setAct | setCom) ? 1'h0 : stateWait + waitInc; // R/Wを跨ぐ間隔をチェックするため、R/Wコマンドの発行でクリアし自動インクリメントするカウンター 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); // 通常アクセスのiReqは、バンクがBusyの場合マスク assign tiReq = iReq & !iAct; assign tpReq = pReq; // ----------------------------------------------------------------------------- // Normal Access Bank Count // バンクごとの通常アクセス期間(Busy)フラグiTermを生成 // iReq & iGntでカウントを1にセット、終了フラグiDoneでクリアする 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 // iAccessはiTermをまとめたもの、ステートマシンで割り込みアクセス待ちに使う always @(posedge clk or negedge reset_n) if (!reset_n) iAccess <= #1 1'b0; else iAccess <= #1 |iTermD; // カウント判定値ACCはR/Wで異なるため、アクセスの種別をバンクごとに記録しておく 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; // iCntだけでiTermを生成できるが、FF間の論理段数を減らすため補助的なフラグをFFで用意 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 // 通常アクセスの指定バンクからBusy信号を抽出、iReqにマスクする(iBankはiAddr[5:3]固定) assign iAct = iTerm[iBank]; // ----------------------------------------------------------------------------- // Special Access Count // 割り込みアクセス期間(Busy)フラグpAccessを生成 // pReq & pGntでカウントを1にセット、終了フラグpDoneでクリアする // その他は通常アクセスと同じ 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 // 1回のマスターアクセスで2回のスレーブアクセスを行うため、2回目に使用するアドレスを保存 always @(posedge clk) if (iAlloc) fifoAddr <= #1 iAddr; // ----------------------------------------------------------------------------- // Flags // sdcRd, sdcWrに出力するコマンドタイミング、ステートマシンのWACTとRACTでタネを生成しラッチ 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 // 特殊カウンターactFIFOは32サイクル分のActivateコマンド発行の履歴を管理 // sumFuncはパラメータで必要領域だけをマスクし、そこの含まれる1の数を数える 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 // cs_n信号などは、ステートマシンの状態から作るのではなく、この便利信号から生成する 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 // DDRの制御信号は負論理、setActとsetComはステートマシンの組み合わせ変数なので論理段数が深いので注意 // それぞれの最初の式は割り込みアクセス用で、cs_n信号以外はpAddrの特定bitをアサインさせている always @(posedge clk or negedge reset_n) if (!reset_n) cs_n <= #1 1'b1; else cs_n <= #1 ~( setAct & statPrev | 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のバンク信号とアドレス信号 // それぞれの最初の式は割り込みアクセス用で、それぞれpAddr[14:12]とpAddr[31:16]をアサインさせている 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[5:3]; 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; // 通常アクセスのRowアドレスはiAddrから生成、パラメータ文で定義したROWSをLSBに切り出し assign rowAddr = addrRowFunc(tmpAddr, ROWS); // 通常アクセスのColumnアドレスはラッチアドレスから生成 assign colAddr = addrColFunc(tmpAddr); // ************************** FUNCTIONS and TASKS ****************************** // 入力アドレスからRowアドレスへのマッピング // rsはパラメータ文で定義した値なので簡単に表現できるが、レジスタ化を考慮した記述にする 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のワード長が変われば、最初のif文の3の数字が変わる(ここでは8bitなので8バーストを表現できる3) 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+3]; else if (i < 11) // ap addrColFunc[i] = 1'b1; else if (i < 12) addrColFunc[i] = addr[13]; else if (i < 13) // bc addrColFunc[i] = 1'b1; else addrColFunc[i] = addr[i+1]; endfunction // 特殊カウンター用のマスク生成 function [31:0] spFunc; input [4:0] sp; input [4:0] bias; reg [5:0] tmp; reg [4:0] sft; integer i; begin // 最初に補正値を引いておく(負であれば0) tmp = {1'd0, sp} - {1'd0, bias}; sft = (~|sp | tmp[5]) ? 5'h00 : tmp[4:0]; // 補正値を境界に、LSB方向に1、MSB方向に0(LSBは必ず1) for (i=0; i<32; i=i+1) spFunc[i] = (sft < i[4:0]) ? 1'b0 : 1'b1; end endfunction // 補正値を引き、0以下は0にするだけ 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 // 特殊カウンター内の1の個数を数える // 4つ以上のActivateは入らない制御なので、4まで数えればよい 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 ▲