CRCモジュール(Verilog-HDL) テストベンチ

以前、弊社で作成したVerilog-HDLのCRCモジュールのテストベンチを公開致します。
簡単に数種類のテストを行っているだけで、網羅的なテストを目的としておりません。インタフェースや使い方の確認などにご利用いただければと思います。

【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

タグ


2017年6月2日 | コメント/トラックバック(0)|

カテゴリー:技術情報

Quartus Prime スタンダード・エディション導入のお知らせ

弊社では、従来Altera FPGAの開発ではQuartus II サブスクリプション・エディションを使用しておりましたが、この度、「Quartus Prime 大特価キャンペーン」を活用させて頂き、Quartus Prime スタンダード・エディションを導入いたしましたのでご報告致します。
引き続き宜しくお願い致します。

タグ


2016年11月5日 | コメント/トラックバック(0)|

カテゴリー:お知らせ

XILINX(ISE) カスタム AXI-Master IPのシミュレーション

AXIマスターオリジナルIPを製作する為に、Xilinx社提供のサンプルコードでのシミュレーションをご紹介します。
本来は、Xilinx社より提供されるAXI Bus Functional Model (BFM)を使用すれば良いのですが、こちらは有償となっておりますので、MicroBlazeのIPを接続してシミュレーションする環境をご紹介いたします。

プロジェクトの方針

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にコピーします。
MicroBoard1

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

MicroBoardプロジェクトの作成

ISEプロジェクトを作成します。
MicroBoardPrj1

Evaliation Development BoardにAvnet S6LX9 MicroBoard RevBを選択します。
MicroBoardPrj2

その他は変更せずにfinishまで進めます。

XPSプロジェクトの作成

New Source WizardでISEプロジェクトに新しくEmbedded Processorを追加します。
EmbeddedProcessor1

New Source Wizardをfinishまで進めると、XPSが起動しBSB Wizardの使用を確認されるので、Yesを選択します。
MicroBoardPrj3

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

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

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

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

XPSプロジェクトへのAXI-Master IPの追加

BSB Wizardが終了するとXPSが起動します。
MicroBoardXps1

今回は、AXI-MASTERのシミュレーションに特化しますのでaxilite_0とmicroblaze関連のIP及びdebug_moduleを削除します。
MicroBoardXps2

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

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

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

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(ディフォルト値)とします。
その他は変更不要です。
MicroBoardXps6

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

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

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

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

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

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

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

Graphic Design Viewを確認します。
MicroBoardXpsConnect2

Design Rule Checkを行いErrorおよびWarningがないことを確認してXPSを終了します。

ISEプロジェクトの完成

ISEに戻って、Generate Top HDL Sourceを実行します。
IseProj1

AXI_MASTER_TEST_top.vが生成されます。
IseProj2

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

AXI_MASTER_TEST_topを選択します。
IseProj4

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

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

IseProj6a

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

【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を実行すると、ワーニングが発生します。
ISim1

Isimの方を確認しても、確かに、Dq 32ビット, Addr 14ビット, DM 4ビットとなっています。
ISim2

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

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

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

タグ


2015年11月10日 | コメントは受け付けていません。|

カテゴリー:技術情報

CRCモジュール(Verilog-HDL)

弊社で作成したVerilog-HDLのCRCモジュールをご紹介いたします。
入力データビット幅、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;

CRC7(8bit)

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;

CRC7(1bit)

同じく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;

CRC16_CCITT

適当な値で{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;

CRC16_CCITT(FFFF_INV)

適当な値で{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;

CRC64_ECMA_182

適当な値で{DE,AD,BE,EF}を入力しています。CRC-64の結果は64’h3DF370C78407B980となります。
{3D,F3,70,C7,84,07,B9,80}を入力すると、CRC-64の結果は0となります。

タグ


2015年9月12日 | コメントは受け付けていません。|

カテゴリー:技術情報

遅延モジュール(Verilog-HDL / Xilinx)

弊社のXilinx社製FPGAのRTL開発で使用しております遅延モジュールをご紹介いたします。

パイプラインにおける遅延調整の場合、ロジックの変更によって遅延量の変更が都度発生します。
その度に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
SCH
 

IFF_USE = 0, OFF_USE = 0 の場合
IOB00
 

IFF_USE = 1, OFF_USE = 0 の場合
IOB10
 

IFF_USE = 0, OFF_USE = 1 の場合
IOB01
IOB propertiesのReg(s)欄を確認すると、IFFあるいはOFFが使用されています。

ARESET_USE = 0 (同期リセットの場合)
fdr
FDR : D Flip-Flop with Synchronous Reset

ARESET_USE = 1 (非同期リセットの場合)
fdc
FDC : D Flip-Flop with Asynchronous Clear

タグ


2015年8月31日 | コメントは受け付けていません。|

カテゴリー:技術情報

このページの先頭へ

イメージ画像