CRCモジュール(Verilog-HDL) テストベンチ
簡単に数種類のテストを行っているだけで、網羅的なテストを目的としておりません。インタフェースや使い方の確認などにご利用いただければと思います。
【crc_tf.v】
//% @file //% @brief crc_tf //% CRC演算テストベンチ module crc_tf; parameter CLK_CYCLE = 10000;// 100MHz //parameter CRC_WIDTH = 7;// CRCデータ幅 parameter CRC_WIDTH = 16;// CRCデータ幅 //parameter CRC_WIDTH = 64;// CRCデータ幅 // CRC初期値 ALL 0 parameter [CRC_WIDTH-1:0] SEED_VAL = {CRC_WIDTH{1'b0}}; // CRC初期値 ALL 1 //parameter [CRC_WIDTH-1:0] SEED_VAL = {CRC_WIDTH{1'b1}}; parameter DATA_WIDTH = 8;// データ幅 //parameter DATA_WIDTH = 2;// データ幅 //parameter DATA_WIDTH = 1;// データ幅 // 出力反転無し parameter OUTPUT_EXOR = {CRC_WIDTH{1'b0}}; // 出力反転有り //parameter OUTPUT_EXOR = {CRC_WIDTH{1'b1}}; parameter [CRC_WIDTH-1:0] POLYNOMIAL = (CRC_WIDTH == 7)? 7'h09 : // CRC7 X^7+X^3+1 (CRC_WIDTH == 16)? 16'h1021 :// CCITT CRC16 X^16+X^12+X^5+1 //(CRC_WIDTH == 16)? 16'h8005 :// CRC16 X^16+X^15+X^2+1 (CRC_WIDTH == 64)? 64'h42F0E1EBA9EA3693 : // CRC64(ECMA-182) 'h0; // Inputs reg CLK; reg RESET_N; reg IN_CLR; reg IN_ENA; reg [DATA_WIDTH-1:0] IN_DATA; // Outputs wire [CRC_WIDTH-1:0] OUT_CRC; // Instantiate the Unit Under Test (UUT) crc # ( .DATA_WIDTH(DATA_WIDTH), .CRC_WIDTH(CRC_WIDTH), .POLYNOMIAL(POLYNOMIAL), .SEED_VAL(SEED_VAL), .OUTPUT_EXOR(OUTPUT_EXOR) ) uut ( .CLK(CLK), .RESET_N(RESET_N), .IN_CLR(IN_CLR), .IN_ENA(IN_ENA), .IN_DATA(IN_DATA), .OUT_CRC(OUT_CRC) ); initial begin CLK = 1'b1;#(CLK_CYCLE / 2); forever begin CLK = ~CLK;#(CLK_CYCLE / 2); end end task task_wait; input integer wait_time; begin repeat(wait_time)@(posedge CLK); end endtask task task_crc7_1byte_test; input [7:0] data0; input [7:0] data1; input [7:0] data2; input [7:0] data3; input [7:0] data4; input integer wait_time; input [6:0] crc; begin @(posedge CLK); IN_CLR = 1; task_wait(1); IN_CLR = 0; task_wait(wait_time); IN_ENA = 1'b1; IN_DATA = data0; task_wait(1); IN_DATA = data1; task_wait(1); IN_DATA = data2; task_wait(1); IN_DATA = data3; task_wait(1); IN_DATA = data4; task_wait(1); IN_ENA = 1'b0; task_wait(wait_time); IN_ENA = 1'b1; IN_DATA = {crc, 1'b0}; task_wait(1); IN_DATA = 8'h00; IN_ENA = 1'b0; end endtask task task_8bit_serial; input [7:0] data; integer i; begin for (i = 0; i < 8; i = i + 1) begin IN_DATA = data[7-i]; task_wait(1); end end endtask task task_4x2bit_serial; input [7:0] data; integer i; begin for (i = 0; i < 4; i = i + 1) begin IN_DATA[0] = data[7-i*2-1]; IN_DATA[1] = data[7-i*2]; task_wait(1); end end endtask task task_7bit_serial; input [6:0] data; integer i; begin for (i = 0; i < 7; i = i + 1) begin IN_DATA = data[6-i]; task_wait(1); end end endtask task task_crc7_1bit_test; input [7:0] data0; input [7:0] data1; input [7:0] data2; input [7:0] data3; input [7:0] data4; input integer wait_time; input [6:0] crc; begin IN_CLR = 1; task_wait(1); IN_CLR = 0; task_wait(wait_time); IN_ENA = 1'b1; task_8bit_serial(data0); task_8bit_serial(data1); task_8bit_serial(data2); task_8bit_serial(data3); task_8bit_serial(data4); IN_ENA = 1'b0; task_wait(wait_time); IN_ENA = 1'b1; task_7bit_serial(crc); IN_DATA = 1'b0; IN_ENA = 1'b0; end endtask task task_crc16_test; input [7:0] data0; input [7:0] data1; input [7:0] data2; input [7:0] data3; input integer wait_time; input [15:0] crc; begin IN_CLR = 1; task_wait(1); IN_CLR = 0; task_wait(wait_time); IN_ENA = 1'b1; IN_DATA = data0; task_wait(1); IN_DATA = data1; task_wait(1); IN_DATA = data2; task_wait(1); IN_DATA = data3; task_wait(1); IN_ENA = 1'b0; task_wait(wait_time); IN_ENA = 1'b1; IN_DATA = crc[15:8]; task_wait(1); IN_DATA = crc[7:0]; task_wait(1); IN_DATA = 8'h00; IN_ENA = 1'b0; end endtask task task_crc16_2bit_test; input [7:0] data0; input [7:0] data1; input [7:0] data2; input [7:0] data3; input integer wait_time; input [15:0] crc; begin IN_CLR = 1; task_wait(1); IN_CLR = 0; task_wait(wait_time); IN_ENA = 1'b1; task_4x2bit_serial(data0); task_4x2bit_serial(data1); task_4x2bit_serial(data2); task_4x2bit_serial(data3); IN_ENA = 1'b0; task_wait(wait_time); IN_ENA = 1'b1; task_4x2bit_serial(crc[15:8]); task_4x2bit_serial(crc[7:0]); IN_DATA = 1'b0; IN_ENA = 1'b0; end endtask task task_crc64_test; input [7:0] data0; input [7:0] data1; input [7:0] data2; input [7:0] data3; input integer wait_time; input [63:0] crc; begin IN_CLR = 1; task_wait(1); IN_CLR = 0; task_wait(wait_time); IN_ENA = 1'b1; IN_DATA = data0; task_wait(1); IN_DATA = data1; task_wait(1); IN_DATA = data2; task_wait(1); IN_DATA = data3; task_wait(1); IN_ENA = 1'b0; task_wait(wait_time); IN_ENA = 1'b1; IN_DATA = crc[63:56]; task_wait(1); IN_DATA = crc[55:48]; task_wait(1); IN_DATA = crc[47:40]; task_wait(1); IN_DATA = crc[39:32]; task_wait(1); IN_DATA = crc[31:24]; task_wait(1); IN_DATA = crc[23:16]; task_wait(1); IN_DATA = crc[15:8]; task_wait(1); IN_DATA = crc[7:0]; task_wait(1); IN_DATA = 8'h00; IN_ENA = 1'b0; end endtask initial begin RESET_N = 0; IN_CLR = 0; IN_ENA = 0; IN_DATA = 0; task_wait(100); RESET_N = 1; task_wait(100); if (CRC_WIDTH == 7) begin if (DATA_WIDTH == 8) begin // SD CMD 0 task_crc7_1byte_test( 8'h40, 8'h00, 8'h00, 8'h00, 8'h00, 10, 7'h4A); task_wait(100); // SD CMD 8 task_crc7_1byte_test( 8'h48, 8'h00, 8'h00, 8'h01, 8'hAA, 10, 7'h43); task_wait(100); // SD CMD 16 task_crc7_1byte_test( 8'h50, 8'h00, 8'h00, 8'h02, 8'h00, 10, 7'h0A); task_wait(100); end else if (DATA_WIDTH == 1) begin // SD CMD 0 task_crc7_1bit_test( 8'h40, 8'h00, 8'h00, 8'h00, 8'h00, 10, 7'h4A); task_wait(100); // SD CMD 8 task_crc7_1bit_test( 8'h48, 8'h00, 8'h00, 8'h01, 8'hAA, 10, 7'h43); task_wait(100); // SD CMD 16 task_crc7_1bit_test( 8'h50, 8'h00, 8'h00, 8'h02, 8'h00, 10, 7'h0A); task_wait(100); end end else if (CRC_WIDTH == 16) begin if (DATA_WIDTH == 8) begin if ((SEED_VAL == 16'h0) && (OUTPUT_EXOR == 16'h0)) begin // "1234" task_crc16_test( 8'h31, 8'h32, 8'h33, 8'h34, 2, 16'hD789); task_wait(100); // "!9qK" task_crc16_test( 8'h21, 8'h39, 8'h71, 8'h4B, 2, 16'hD809); task_wait(100); end else if ((SEED_VAL == 16'hFFFF) && (OUTPUT_EXOR == 16'hFFFF)) begin // "1234" CRC = ACB6 task_crc16_test( 8'h31, 8'h32, 8'h33, 8'h34, 2, 16'h5349); task_wait(100); // "!9qK" CRC = A336 task_crc16_test( 8'h21, 8'h39, 8'h71, 8'h4B, 2, 16'h5CC9); task_wait(100); end end else if (DATA_WIDTH == 2) begin if ((SEED_VAL == 16'h0) && (OUTPUT_EXOR == 16'h0)) begin // "1234" task_crc16_2bit_test( 8'h31, 8'h32, 8'h33, 8'h34, 2, 16'hD789); task_wait(100); // "!9qK" task_crc16_2bit_test( 8'h21, 8'h39, 8'h71, 8'h4B, 2, 16'hD809); task_wait(100); end end end else if (CRC_WIDTH == 64) begin task_crc64_test('hDE, 'hAD, 'hBE, 'hEF, 4, 64'h3DF370C78407B980); task_wait(100); end $stop; end endmodule
タグ
FPGA、Verilog-HDL、ハードウェア2017年6月2日 | コメント/トラックバック(0)|
カテゴリー:技術情報
Quartus Prime スタンダード・エディション導入のお知らせ
引き続き宜しくお願い致します。
タグ
FPGA2016年11月5日 | コメント/トラックバック(0)|
カテゴリー:お知らせ
XILINX(ISE) カスタム AXI-Master IPのシミュレーション
本来は、Xilinx社より提供されるAXI Bus Functional Model (BFM)を使用すれば良いのですが、こちらは有償となっておりますので、MicroBlazeのIPを接続してシミュレーションする環境をご紹介いたします。
プロジェクトの方針
- ISE 14.7を使用する
- Avnet社製MicroBoardに搭載することを前提に進める
- AR# 37425 – 12.3 EDK、12.3 ISE – カスタム AXI IP コアの作成方法のaxi_master_v1_00_aを使用する
- AXI Bus Functional Model (BFM)は使用しない
- プロジェクトの中にEmbedded Processor(MicroBlaze)を含めない
Avnet社製MicroBoardの環境準備
avnet社のホームページよりMicroBoardのXBDを入手します。EDK 14.3 XBD/IP-XACT Files : avnet_edk14_3_xbd_files_9_11_2012_spartan.zip
http://www.em.avnet.com/en-us/design/drc/Pages/Xilinx-Spartan-6-FPGA-LX9-MicroBoard.aspxのSupport and Downloadsから入手できます。
avnet_edk14_3_xbd_files.zip/boards/Avnet_S6LX9_MicroBoard_RevBを/Xilinx/14.7/ISE_DS\EDK/board/Xilinx/boardsにコピーします。

avnet_edk14_3_xbd_files.zip/ipxact/S6_MicroBoard_v1_0を/Xilinx/14.7/ISE_DS\EDK/board/Xilinx/ipxactにコピーします。

MicroBoardプロジェクトの作成
ISEプロジェクトを作成します。
Evaliation Development BoardにAvnet S6LX9 MicroBoard RevBを選択します。

その他は変更せずにfinishまで進めます。
XPSプロジェクトの作成
New Source WizardでISEプロジェクトに新しくEmbedded Processorを追加します。
New Source Wizardをfinishまで進めると、XPSが起動しBSB Wizardの使用を確認されるので、Yesを選択します。

AXI Systemがデフォルトで選択されていますので、そのまま次に進みます。

BoardおよびSystemに関する設定はデフォルトのままで次に進みます。

processorとperipheralに関する設定です。

今回は、AXI-MASTERのシミュレーションに特化しますので不要なペリフェラルをすべて削除します。MCB3_LPDDR(Cached)以外はすべてRemoveして、Finishします。

XPSプロジェクトへのAXI-Master IPの追加
BSB Wizardが終了するとXPSが起動します。
今回は、AXI-MASTERのシミュレーションに特化しますのでaxilite_0とmicroblaze関連のIP及びdebug_moduleを削除します。

AR37425.zipをxilinx社のホームページからダウンロード-解凍して、axi_master_v1_00_aフォルダをAXI_MASTER_TEST/AXI_MASTER_TEST/pcoresにコピーします。

Project->Rescan User Repositoriesをクリックすると、IP CatalogにAXI Masterが追加されます。

MCB_LPDDRのAddressを確認します。0xA4000000-0xA7FFFFFFになっています。
Project->Rescan User Repositoriesをクリックすると、IP CatalogにAXI Masterが追加されます。

AXI Master IPを追加します。
C_M_AXI_TARGETは、前項で確認したMCB_LPDDRの先頭アドレスである0xA4000000を設定します。
C_M_AXI_BURST_LENは、AXIのバースト長を指定します。今回はディフォルトのままにします。
C_OFFSET_WIDTHはサンプルの書き込み範囲のビット数を示しております。初期値は9になっていますので0xA4000000から0xA40001FFまでの512バイトのWrite/Readテストを行います。
C_M_AXI_PROTOCOLはAXI(ディフォルト値)とします。
その他は変更不要です。

axi_master_0が追加されますので、axi_master_0をaxi4_0にバス接続します。

MCB3_LPDDRをaxi4_0にバス接続します。

これで、axi_master_0とMCB3_LPDDRがAXI4で接続されました。

LPDDR SDRAMのシミュレーションモデルを生成する為に、MCB3_LPDDRのMIGを起動します。

設定の変更は必要ありませんので、そのまま進んでいき、finishします。

AXI_MASTER_TEST\AXI_MASTER_TEST\__xps\MCB3_LPDDRにLPDDR SDRAMのシミュレーションモデルが生成されます。

axi_master_0のポートを接続します。
- axi_master_0::ERROR – External Ports axi_master_0_error(新規)
- axi_master_0::M_AXI::ACLK – clock_generator_0::CLKOUT2

Graphic Design Viewを確認します。

Design Rule Checkを行いErrorおよびWarningがないことを確認してXPSを終了します。
ISEプロジェクトの完成
ISEに戻って、Generate Top HDL Sourceを実行します。
AXI_MASTER_TEST_top.vが生成されます。

New Source WizardでISEプロジェクトに新しくテストベンチファイルを追加します。

AXI_MASTER_TEST_topを選択します。

先ほど生成したLPDDR SDRAMのシミュレーションモデル「AXI_MASTER_TEST/AXI_MASTER_TEST/__xps\MCB3_LPDDRのlpddr_model.v」をプロジェクトに追加します。

lpddr_modelがプロジェクトに追加されました。

lpddr_modelとの接続等をテストベンチファイルAXI_MASTER_TEST_tf.vに記述します。

【AXI_MASTER_TEST_tf.v】
`timescale 1ps / 1ps module AXI_MASTER_TEST_tf; // Inputs reg RESET; reg CLK_66MHZ; // Outputs wire mcbx_dram_we_n; wire mcbx_dram_udm; wire mcbx_dram_ras_n; wire mcbx_dram_ldm; wire mcbx_dram_clk_n; wire mcbx_dram_clk; wire mcbx_dram_cke; wire mcbx_dram_cas_n; wire [1:0] mcbx_dram_ba; wire [12:0] mcbx_dram_addr; wire axi_master_0_error; // Bidirs wire rzq; wire mcbx_dram_udqs; wire mcbx_dram_dqs; wire [15:0] mcbx_dram_dq; // Instantiate the Unit Under Test (UUT) AXI_MASTER_TEST_top uut ( .rzq(rzq), .mcbx_dram_we_n(mcbx_dram_we_n), .mcbx_dram_udqs(mcbx_dram_udqs), .mcbx_dram_udm(mcbx_dram_udm), .mcbx_dram_ras_n(mcbx_dram_ras_n), .mcbx_dram_ldm(mcbx_dram_ldm), .mcbx_dram_dqs(mcbx_dram_dqs), .mcbx_dram_dq(mcbx_dram_dq), .mcbx_dram_clk_n(mcbx_dram_clk_n), .mcbx_dram_clk(mcbx_dram_clk), .mcbx_dram_cke(mcbx_dram_cke), .mcbx_dram_cas_n(mcbx_dram_cas_n), .mcbx_dram_ba(mcbx_dram_ba), .mcbx_dram_addr(mcbx_dram_addr), .RESET(RESET), .CLK_66MHZ(CLK_66MHZ), .axi_master_0_error(axi_master_0_error) ); lpddr_model mem ( .Dq(mcbx_dram_dq), .Dqs({mcbx_dram_udqs, mcbx_dram_dqs}), .Addr(mcbx_dram_addr), .Ba(mcbx_dram_ba), .Clk(mcbx_dram_clk), .Clk_n(mcbx_dram_clk_n), .Cke(mcbx_dram_cke), .Cs_n(1'b0), .Ras_n(mcbx_dram_ras_n), .Cas_n(mcbx_dram_cas_n), .We_n(mcbx_dram_we_n), .Dm({mcbx_dram_udm, mcbx_dram_ldm}) ); initial begin // Initialize Inputs RESET = 1; CLK_66MHZ = 0; // Wait 100 ns for global reset to finish #100; RESET = 0; // Add stimulus here forever begin CLK_66MHZ = ~CLK_66MHZ; #(7576); end end endmodule
シミュレーションの実効
Isim simulatorを実行すると、ワーニングが発生します。
Isimの方を確認しても、確かに、Dq 32ビット, Addr 14ビット, DM 4ビットとなっています。

プロジェクトのAutomatic `includesにあるlpddr_model_parameters.vhを見てみると、メモリ種別に対するifdefがあります。
XPSを再度立ち上げて、MCB3_LPDDRのMIGを起動しすると、MCB3_LPDDRのメモリパートは、MCBMT46H32M16XXXX-5が選択されています。

isim Process Propertiesの-d(Specify `define Macro Name and Value)にx512Mb|sg5|x16と入力します。(sg5 = -5 (CL=3))
パラメータは必ず”|”で結合してください。スペースも不可です。
x512Mb sg5 x16
x512Mb | sg5 | x16
これらでは、認識しません。

isimを再起動すると、mem::Addr[12:0] mem::Dq[15:0] mem::Dm[1:0]となり、シミュレーションが成功します。

タグ
FPGA、Verilog-HDL2015年11月10日 | コメントは受け付けていません。|
カテゴリー:技術情報
CRCモジュール(Verilog-HDL)
入力データビット幅、CRCデータ幅、多項式、シード値、CRC出力反転をパラメータ設定できます。
DATA_WIDTHは、入力データのビット幅を設定します。シリアル通信の場合などに、1ビット毎での入力を行うことも可能ですし、8ビットにして1バイト分の演算を1クロックサイクルで処理するなど自由に設定を行うことが出来ます。それによってデバイス、ロジック規模、クロックレートによって最適な使用方法を選択できます。
CRC_WIDTHは、CRCのビット幅を設定します。
POLYNOMIALは、多項式を設定します。例えばCRC-16-CCITT x16+x12+x5+1の場合、16’h1021となります。
SEED_VALは、初期値を設定します。通常は0を設定します。
OUTPUT_EXORは、出力の反転設定をします。通常は0を設定します。
【crc.v】
//% @file //% @brief crc //% CRC演算 module crc # ( parameter DATA_WIDTH = 8,//% データ幅 parameter CRC_WIDTH = 16,//% CRCデータ幅 parameter [CRC_WIDTH-1:0] POLYNOMIAL = 16'h1021,//% 生成多項式 parameter [CRC_WIDTH-1:0] SEED_VAL = 16'h0,//% シード値 parameter OUTPUT_EXOR = 16'h0//% 出力反転 ) ( input CLK, //% クロック input RESET_N, //% リセット(負論理) input IN_CLR,//% 入力CRC初期化 input IN_ENA,//% 入力イネーブル input [DATA_WIDTH-1:0] IN_DATA,//% 入力データ output [CRC_WIDTH-1:0] OUT_CRC//% CRC演算結果出力 ); reg [CRC_WIDTH-1:0] crc_reg; /*! CRC演算関数 */ function [CRC_WIDTH-1:0] crc_calc; input [CRC_WIDTH-1:0] in_crc; input in_data; integer i; begin for (i = 0; i < CRC_WIDTH; i = i + 1) begin crc_calc[i] = 1'b0; if (i != 0) crc_calc[i] = in_crc[i-1]; if (POLYNOMIAL[i]) crc_calc[i] = crc_calc[i] ^ in_crc[CRC_WIDTH-1] ^ in_data; end end endfunction /*! CRC演算ループ関数 */ function [CRC_WIDTH-1:0] crc_calc_l; input [CRC_WIDTH-1:0] in_crc; input [DATA_WIDTH-1:0] in_data; integer i; begin crc_calc_l = in_crc; for (i = 0; i < DATA_WIDTH; i = i + 1) begin crc_calc_l = crc_calc(crc_calc_l, in_data[(DATA_WIDTH-1)-i]); end end endfunction /*! CRCレジスタ */ always @(posedge CLK) begin: crc_reg_l if (!RESET_N) crc_reg <= SEED_VAL; else begin if (IN_CLR) crc_reg <= SEED_VAL; else if (IN_ENA) crc_reg <= crc_calc_l(crc_reg, IN_DATA); end end assign OUT_CRC = crc_reg ^ OUTPUT_EXOR; endmodule
SDカードで使用しているCRC-7、CRC-16-CCITT、およびCRC-64-ECMA-182でシミュレーションしてみました。
[CRC-7 8ビット入力]
parameter DATA_WIDTH = 8;
parameter CRC_WIDTH = 7;
parameter [CRC_WIDTH-1:0] POLYNOMIAL = 7’h09;
parameter [CRC_WIDTH-1:0] SEED_VAL = 7’h0;
parameter [CRC_WIDTH-1:0] OUTPUT_EXOR = 7’h0;

SDのSPIコマンド セットCMD8 {48,00,00,01,AA}を入力しています。CRC-7の結果は7’h43となります。
7’h43を先頭詰めの8bitにすると8’h86になるので、8’h86を入力すると、CRC-7の結果は0となります。
[CRC-7 1ビット入力]
parameter DATA_WIDTH = 1;
parameter CRC_WIDTH = 7;
parameter [CRC_WIDTH-1:0] POLYNOMIAL = 7’h09;
parameter [CRC_WIDTH-1:0] SEED_VAL = 7’h0;
parameter [CRC_WIDTH-1:0] OUTPUT_EXOR = 7’h0;

同じくSPIコマンド セットCMD8 {48,00,00,01,AA}を入力しています。
結果は、当然ですが8ビット入力時と同じです。
[CRC-16 8ビット入力]
parameter DATA_WIDTH = 8;
parameter CRC_WIDTH = 16;
parameter [CRC_WIDTH-1:0] POLYNOMIAL = 16’h1021;
parameter [CRC_WIDTH-1:0] SEED_VAL = 16’h0;
parameter [CRC_WIDTH-1:0] OUTPUT_EXOR = 16’h0;

適当な値で{21,39,71,4B}を入力しています。CRC-16の結果は16’hD809となります。
{D8,09}を入力すると、CRC-16の結果は0となります。
[CRC-16 8ビット入力 シード値FFFF CRC出力反転]
parameter DATA_WIDTH = 8;
parameter CRC_WIDTH = 16;
parameter [CRC_WIDTH-1:0] POLYNOMIAL = 16’h1021;
parameter [CRC_WIDTH-1:0] SEED_VAL = 16’h0;
parameter [CRC_WIDTH-1:0] OUTPUT_EXOR = 16’h0;

適当な値で{21,39,71,4B}を入力しています。CRC-16の結果は16’hA336となります。
16’hA336をビット反転すると16’h5CC9となりますので5C,C9}を入力すると、CRC-16の結果は16’hFFFFとなります。
[CRC-64-ECMA-182 8ビット入力]
parameter DATA_WIDTH = 8;
parameter CRC_WIDTH = 64;
parameter [CRC_WIDTH-1:0] POLYNOMIAL = 64’h42F0E1EBA9EA3693;
parameter [CRC_WIDTH-1:0] SEED_VAL = 64’h0;
parameter [CRC_WIDTH-1:0] OUTPUT_EXOR = 64’h0;

適当な値で{DE,AD,BE,EF}を入力しています。CRC-64の結果は64’h3DF370C78407B980となります。
{3D,F3,70,C7,84,07,B9,80}を入力すると、CRC-64の結果は0となります。
タグ
FPGA、Verilog-HDL、ハードウェア2015年9月12日 | コメントは受け付けていません。|
カテゴリー:技術情報
遅延モジュール(Verilog-HDL / Xilinx)
パイプラインにおける遅延調整の場合、ロジックの変更によって遅延量の変更が都度発生します。
その度にFFを1段追加あるいは削除するというのは、かなりの面倒な作業と思います。
また、外部入力信号や非同期クロック間転送(CDC)の為のダブルFFシンクロナイザも都度記述するのは、煩わしい作業では無いかと思います。
そこで、ビット幅および遅延量をパラメータ化した遅延モジュールを用意しております。
また、入力ピンおよび出力ピンに直結した場合にIOB内蔵のFFを使用するパラメータも用意しております。
リセットについては、弊社では殆どの場合、同期リセットを使用しておりますが、非同期リセットにも対応できるようにパラメータ化しております。
【delay_ff.v】
//% @file //% @brief delay_ff (for Xilinx FPGA) //% ディレーフリップフロップ module delay_ff # ( parameter DATA_WIDTH = 2,//% データ幅 parameter DELAY_TIME = 3,//% 遅延時間 parameter IFF_USE = 0,//% 初段FF = IOB parameter OFF_USE = 0,//% 最終FF = IOB parameter ARESET_USE = 0//% 非同期リセット使用 ) ( input CLK, //% クロック input RESET_N, //% リセット(負論理) input [DATA_WIDTH-1:0] IN_DATA,//% 入力データ output [DATA_WIDTH-1:0] OUT_DATA//% 出力データ ); wire [DATA_WIDTH-1:0] data[DELAY_TIME:0]; assign data[0] = IN_DATA; assign OUT_DATA = data[DELAY_TIME]; /*! D-FF */ generate genvar i; for (i = 0; i < DELAY_TIME; i = i + 1) begin : gen_d_ff d_ff #( .DATA_WIDTH(DATA_WIDTH), .IOB_USE((i == 0)? IFF_USE : (i == (DELAY_TIME-1))? OFF_USE : 0), .ARESET_USE(ARESET_USE) ) u_d_ff ( .CLK(CLK), .RESET_N(RESET_N), .IN_DATA(data[i]), .OUT_DATA(data[i+1]) ); end endgenerate endmodule
【d_ff.v】
//% @file //% @brief d-ff (for Xilinx FPGA) //% Dタイプフリップフロップ module d_ff # ( parameter DATA_WIDTH = 1,//% データ幅 parameter IOB_USE = 0,//% IOB使用 parameter ARESET_USE = 0//% 非同期リセット使用 ) ( input CLK, //% クロック input RESET_N, //% リセット(負論理) input [DATA_WIDTH-1:0] IN_DATA,//% 入力データ output [DATA_WIDTH-1:0] OUT_DATA//% 出力データ ); (* IOB = (IOB_USE)? "TRUE" : "FALSE" *) reg [DATA_WIDTH-1:0] data_reg; assign OUT_DATA = data_reg; /*! データレジスタ */ generate if (ARESET_USE) begin always @(posedge CLK or negedge RESET_N) begin: data_reg_l if (!RESET_N) data_reg <= {DATA_WIDTH{1'b0}}; else data_reg <= IN_DATA; end end else begin always @(posedge CLK) begin: data_reg_l if (!RESET_N) data_reg <= {DATA_WIDTH{1'b0}}; else data_reg <= IN_DATA; end end endgenerate endmodule上記コードをSpartan-6にインプリメントしてみます。
View RTL Schematic
IFF_USE = 0, OFF_USE = 0 の場合
IFF_USE = 1, OFF_USE = 0 の場合
IFF_USE = 0, OFF_USE = 1 の場合
IOB propertiesのReg(s)欄を確認すると、IFFあるいはOFFが使用されています。
ARESET_USE = 0 (同期リセットの場合)
FDR : D Flip-Flop with Synchronous Reset
ARESET_USE = 1 (非同期リセットの場合)
FDC : D Flip-Flop with Asynchronous Clear
タグ
FPGA、Verilog-HDL、ハードウェア2015年8月31日 | コメントは受け付けていません。|
カテゴリー:技術情報