論理回路デザイン |
|
/* **************************** MODULE PREAMBLE ******************************** Copyright (c) 2011, ArchiTek This document constitutes confidential and proprietary information of ArchiTek. All rights reserved. */ // ***************************** MODULE HEADER ********************************* module afifo ( iVld, iStall, iData, oVld, oStall, oData, iReset, iClk, oReset, oClk, reset_n ); // ************************ PARAMETER DECLARATIONS ***************************** parameter W = 32; // Data Length parameter DR = 2; // Depth Radix parameter D = 1<<DR; // *************************** I/O DECLARATIONS ******************************** input iVld; output iStall; input [W-1:0] iData; output oVld; input oStall; output [W-1:0] oData; // 入力側の同期リセットとクロック input iReset; input iClk; // 出力側の同期リセットとクロック input oReset; input oClk; // グローバルな非同期リセットを用意 input reset_n; // ************************** LOCAL DECLARATIONS ******************************* reg iStall; wire iStallD; reg oVld; wire oVldD; // グレーコードで入力ポインタを格納 reg [DR:0] iGrPtr; // Gray Code Base wire [DR:0] iGrPtrD; wire [DR:0] iPtr; wire [DR:0] iPtrD; // グレーコードで出力ポインタを格納 reg [DR:0] oGrPtr; // Gray Code Base wire [DR:0] oGrPtrD; wire [DR:0] oPtr; wire [DR:0] oPtrD; // 出力側で使う入力ポインタのダブルシンクロナイズ用のFF reg [DR:0] iGrPtr_s0; reg [DR:0] iGrPtr_s1; wire [DR:0] iPtr_s1; // 入力側で使う出力ポインタのダブルシンクロナイズ用のFF reg [DR:0] oGrPtr_s0; reg [DR:0] oGrPtr_s1; wire [DR:0] oPtr_s1; reg [W-1:0] oData; wire iAlloc = iVld & !iStall; wire oAlloc = oVld & !oStall; reg [W-1:0] mem[0:D-1]; // ****************************** MODULE BODY ********************************** // ----------------------------------------------------------------------------- // Input Domain // 入力クロックドメイン側の処理(ポインタ以外は従来と変わらず) always @(posedge iClk) if (iAlloc) mem[iPtr[DR-1:0]] <= #1 iData; always @(posedge iClk or negedge reset_n) if (!reset_n) iStall <= #1 1'b0; else if (iReset) iStall <= #1 1'b0; else iStall <= #1 iStallD; always @(posedge iClk or negedge reset_n) if (!reset_n) iGrPtr <= #1 {DR+1{1'b0}}; else if (iReset) iGrPtr <= #1 {DR+1{1'b0}}; else iGrPtr <= #1 iGrPtrD; // ポインタインクリメントのため、通常ポインタに変換 assign iPtr = grayDecFunc(iGrPtr); assign iPtrD = iPtr + iAlloc; // FFに格納するため、グレーコードに変換 assign iGrPtrD = grayEncFunc(iPtrD); // 比較は通常ポインタとダブルシンクロナイズした通常ポインタ assign iStallD = (iPtrD[DR] != oPtr_s1[DR]) & (iPtrD[DR-1:0] == oPtr_s1[DR-1:0]); // ----------------------------------------------------------------------------- // Output Domain // 出力クロックドメイン側の処理(ポインタ以外は従来と変わらず) always @(posedge oClk) if (!oStall) oData <= #1 mem[oPtrD[DR-1:0]]; always @(posedge oClk or negedge reset_n) if (!reset_n) oVld <= #1 1'b0; else if (oReset) oVld <= #1 1'b0; else oVld <= #1 oVldD; always @(posedge oClk or negedge reset_n) if (!reset_n) oGrPtr <= #1 {DR+1{1'b0}}; else if (oReset) oGrPtr <= #1 {DR+1{1'b0}}; else oGrPtr <= #1 oGrPtrD; // ポインタインクリメントのため、通常ポインタに変換 assign oPtr = grayDecFunc(oGrPtr); assign oPtrD = oPtr + oAlloc; // FFに格納するため、グレーコードに変換 assign oGrPtrD = grayEncFunc(oPtrD); // 比較は通常ポインタとダブルシンクロナイズした通常ポインタ assign oVldD = (iPtr_s1 != oPtrD); // ----------------------------------------------------------------------------- // Sync FF // ダブルシンクロナイズFFを作成(組み合わせなしの単純ラッチ) always @(posedge oClk or negedge reset_n) if (!reset_n) begin iGrPtr_s0 <= #1 {DR+1{1'b0}}; iGrPtr_s1 <= #1 {DR+1{1'b0}}; end else if (oReset) begin iGrPtr_s0 <= #1 {DR+1{1'b0}}; iGrPtr_s1 <= #1 {DR+1{1'b0}}; end else begin iGrPtr_s0 <= #1 iGrPtr; // 1st Sync iGrPtr_s1 <= #1 iGrPtr_s0; // 2nd Sync end always @(posedge iClk or negedge reset_n) if (!reset_n) begin oGrPtr_s0 <= #1 {DR+1{1'b0}}; oGrPtr_s1 <= #1 {DR+1{1'b0}}; end else if (iReset) begin oGrPtr_s0 <= #1 {DR+1{1'b0}}; oGrPtr_s1 <= #1 {DR+1{1'b0}}; end else begin oGrPtr_s0 <= #1 oGrPtr; // 1st Sync oGrPtr_s1 <= #1 oGrPtr_s0; // 2nd Sync end // ダブルシンクロナイズしたポインタを通常ポインタに変換 assign iPtr_s1 = grayDecFunc(iGrPtr_s1); assign oPtr_s1 = grayDecFunc(oGrPtr_s1); // ************************** FUNCTIONS and TASKS ****************************** // 数値からグレーコードへの変換 function [DR:0] grayEncFunc; input [DR:0] in; begin grayEncFunc = in ^ (in >> 1); end endfunction // グレーコードから数値への変換 function [DR:0] grayDecFunc; input [DR:0] in; reg [DR:0] mat; reg [DR:0] result; integer i; integer j; begin for (i=0; i<=DR; i=i+1) begin for (j=0; j<=DR; j=j+1) mat[j] = (i+j > DR) ? 1'b0 : in[i+j]; result[i] = ^mat; end grayDecFunc = result; end endfunction endmodule // *****************************************************************************
回路デザイン > 設計例 [FIFO] > >非同期FIFO このページのTOP ▲