FRAMにアクセス (シミュレーション編)
FRAM I/FブロックをトップとしたRTLシミュレーションになります。
ここでは、テストベンチ記述を記載します。
尚、言語はSystemVerilogとなります。
FRAM I/Fブロックの仕様及びソースコードは以下を参照ください。
nao-milk.hatenablog.com
nao-milk.hatenablog.com
対向モデル
FRAM I/Fブロックの対向モデル(FRAMデバイス)は、シミュレーションモデルがベンダーで提供されていますので、それを入手してください。
テストベンチ
テストベンチは、FRAM I/FブロックとFRAMモデルを配置し、クロック生成及びタスクを準備し、テストシナリオを記述します。
尚、レジスタなどは構造体にした方が便利なため、記述はSystemVerilogにしています。
ヘッダファイル
レジスタの構造体とアドレス 及び よく使う処理をタスク化しています。
// -- // -- レジスタパック // ------------------------------------------------------------------- typedef struct packed { // ** 処理イネーブル reg [31: 1] Non ; // 未使用 reg ENB ; // 処理イネーブル } Register_ENB; typedef struct packed { // ** 制御パラメータ reg [31: 7] Non ; // 未使用 reg [ 6: 5] TOK ; // 取り込みタイミング reg POL ; // シリアルクロック極性 reg [ 3: 0] DIV ; // シリアルクロック分周 } Register_CNT; typedef struct packed { // ** アクセスバイト数 reg [31:21] Non ; // 未使用 reg [20: 0] ACS ; // アクセスバイト数 } Register_ACS; typedef struct packed { // ** 出力バイト数 reg [31:21] Non ; // 未使用 reg [20: 0] OTC ; // 出力バイト数 } Register_OTC; typedef struct packed { // ** 割り込みステータス reg [31: 1] Non ; // 未使用 reg IRS ; // 割り込みステータス } Register_IRS; typedef struct packed { // ** 割り込みマスク reg [31: 1] Non ; // 未使用 reg IRM ; // 割り込みマスク } Register_IRM; typedef struct packed { // ** バッファリード/ライトアドレス reg [31:21] Non ; // 未使用 reg [20: 0] BAD ; // バッファリード/ライトアドレス } Register_BAD; typedef struct packed { // ** バッファリード/ライトデータ reg [31: 8] Non ; // 未使用 reg [ 7: 0] BDT ; // バッファリード/ライトデータ } Register_BDT; struct { reg [31:0] ENB = 'h00; reg [31:0] CNT = 'h04; reg [31:0] ACS = 'h08; reg [31:0] OTC = 'h0C; reg [31:0] IRS = 'h10; reg [31:0] IRM = 'h14; reg [31:0] BAD = 'h18; reg [31:0] BDT = 'h1C; } REG_ADDR; struct { Register_ENB ENB = 32'h0000_0000; Register_CNT CNT = 32'h0000_0000; Register_ACS ACS = 32'h0000_0000; Register_OTC OTC = 32'h0000_0000; Register_IRS IRS = 32'h0000_0000; Register_IRM IRM = 32'h0000_0001; Register_BAD BAD = 32'h0000_0000; Register_BDT BDT = 32'h0000_0000; } REG_DATA; // -- // -- 処理タスク // ------------------------------------------------------------------- // ++ // ++ 書き込みイネーブル ラッチ設定 // +++++++++++++++++++++++++++++++++++++++++++ task SetWREN(); begin $display("\n===== %m (Enable Write) ====="); REG_DATA.ACS.ACS = 0; WrCPU(REG_ADDR.ACS,REG_DATA.ACS); // アクセスバイト数 REG_DATA.OTC.OTC = 0; WrCPU(REG_ADDR.OTC,REG_DATA.OTC); // 出力バイト数 REG_DATA.IRM.IRM = 1; WrCPU(REG_ADDR.IRM,REG_DATA.IRM); // 割り込みマスク REG_DATA.IRS.IRS = 1; WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス クリア RdCPU(REG_ADDR.IRS,REG_DATA.IRS); $display(" >>> Read : %p",REG_DATA.IRS); REG_DATA.BAD.BAD = 0; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス REG_DATA.BDT.BDT ='h06; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル RdCPU(REG_ADDR.ENB,REG_DATA.ENB); while(REG_DATA.ENB.ENB===1) begin repeat(20) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); end REG_DATA.IRS.IRS = 1; WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス クリア REG_DATA.IRM.IRM = 0; WrCPU(REG_ADDR.IRM,REG_DATA.IRM); // 割り込みマスク 解除 end endtask
テストベンチトップ
テストシナリオでは、リセット解除後からマスタモード → スレーブモードのリード系 → スレーブモードのライト系の動作を行い、各コマンドの発行を行っています。
また、FRAMのサイズも 256K×8bit分アクセスするテストを行っています。
最終的にすべて実行し、変数errorが0であれば、問題無しとしています。
尚、レジスタの初期値確認や割り込み動作などは、別のシナリオで確認しています。
データ比較は、
リード(FRAMデバイス → FRAM I/Fブロック)時、FRAMデバイス内の配列とAvalon-MM Master/Slave I/Fで取得したデータが等しいか確認します。
ライト(FRAM I/Fブロック → FRAMデバイス)時、Avalon-MM Slave I/Fブロックにライトしたデータが、FRAMデバイス内の配列と等しいか確認します。
`timescale 1ns/1ps module TB_TOP; integer PERIOD = 0; reg CPU_RST_N = 0; // @@ CPU I/F用 リセット reg CPU_CLK = 0; // @@ CPU I/F用 クロック reg SYS_RST_N = 0; // @@ システム動作用 リセット reg SYS_CLK = 0; // @@ システム動作用 クロック reg MST_SLV = 0; // @@ Avalon-MM Master/Slave切替 [0:Master] reg PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] reg [ 3:0] PRM_DIV = 0; // @@ シリアルクロック周波数設定 reg PRM_POL = 0; // @@ シリアルクロック極性設定 reg [ 1:0] PRM_TAK = 0; // @@ シリアルデータ取り込みタイミング設定 reg [20:0] PRM_ACS = 0; // @@ アクセスバイト数 (最大値:1,048,579) reg [ 1:0] PRM_OTC = 0; // @@ 出力バイト数 (最大値:3) reg PRM_MSK = 1; // @@ 割り込みマスク reg PRM_CLR = 0; // @@ 割り込みクリア reg [31:0] PRM_STA = 0; // @@ Avalon-MM(Master側) ライトベースアドレス reg [ 7:0] PRM_CMD = 0; // @@ RAMコマンド reg [23:0] PRM_ADD = 0; // @@ FRAMアドレス reg SAV_WEN = 0; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) ライトイネーブル reg SAV_REN = 0; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リードイネーブル reg [ 5:0] SAV_ADD = 0; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リード/ライトイネーブル reg [31:0] SAV_WDT = 0; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) ライトデータ reg MAV_WIT = 0; // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ウェイトリクエスト wire SAV_WIT ; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) ウェイトリクエスト wire SAV_RVL ; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リードデータイネーブル wire [31:0] SAV_RDT ; // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リードデータ wire MAV_WEN ; // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ライトイネーブル wire [31:0] MAV_ADD ; // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ライトアドレス wire [ 3:0] MAV_BEN ; // @@ [CPU_CLK↑同期] Avalon-MM(Master側) バイトイネーブル wire [ 7:0] MAV_WDT ; // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ライトデータ wire CPU_IRQ ; // @@ [CPU_CLK↑同期] 割り込み信号 wire MON_ENB ; // @@ [CPU_CLK↑同期] 動作モニタ [0:停止中 1:動作中] wire FRAM_CS_N ; // @@ [SYS_CLK↑同期] FRAM SPI チップセレクト wire FRAM_SCLK ; // @@ [SYS_CLK↑同期] FRAM SPI シリアルクロック wire FRAM_MOSI ; // @@ [SYS_CLK↑同期] FRAM SPI シリアル出力 wire FRAM_MISO ; // @@ [SYS_CLK↑同期] FRAM SPI シリアル入力 wire FRAM_OUTE ; // @@ [SYS_CLK↑同期] FRAM SPI 出力イネーブル[1:出力 0:Hi-Z] // ++ タイミング設定 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Clock波形 real tcCPU_CLK = 20.000; real tpCPU_CLK = 5.000; real tnCPU_CLK = 15.000; real tcSYS_CLK = 5.000; real tpSYS_CLK = 1.000; real tnSYS_CLK = 3.500; // FRAM モデル間遅延 defparam UnDlyFRAM_CS_N.NsStep= 0 ,UnDlyFRAM_CS_N.PsStep= 0; defparam UnDlyFRAM_SCLK.NsStep= 0 ,UnDlyFRAM_SCLK.PsStep= 0; defparam UnDlyFRAM_MOSI.NsStep= 0 ,UnDlyFRAM_MOSI.PsStep= 0; defparam UnDlyFRAM_MISO.NsStep= 0 ,UnDlyFRAM_MISO.PsStep= 0; // -- // -- テストシナリオ // ------------------------------------------------------------------- `define MASTER_MODE `define SLAVE_MODE_READ `define SLAVE_MODE_WRITE reg [ 7:0] PMEM[0:262144]; integer error = 0; `include "TB_HEAD.sv" always @( posedge CPU_CLK ) begin if( (MAV_WEN===1'b1) & (MAV_WIT==0) ) begin if( MAV_BEN[0]===1'b1 ) PMEM[MAV_ADD-PRM_STA] <= MAV_WDT; if( MAV_BEN[1]===1'b1 ) PMEM[MAV_ADD-PRM_STA] <= MAV_WDT; if( MAV_BEN[2]===1'b1 ) PMEM[MAV_ADD-PRM_STA] <= MAV_WDT; if( MAV_BEN[3]===1'b1 ) PMEM[MAV_ADD-PRM_STA] <= MAV_WDT; end MAV_WIT <= $random; end defparam FRAM.hasSN = 1; integer ei; initial begin #0; repeat(10) @(PERIOD); @(posedge CPU_CLK); #1 CPU_RST_N = 1; @(posedge SYS_CLK); #1 SYS_RST_N = 1; // @@ // @@ Master Mode // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ `ifdef MASTER_MODE repeat(20) @(PERIOD); MST_SLV = 0; // @@ Avalon-MM Master/Slave切替 [0:Master] // ++ [ 初期設定 ] ++ PRM_STA = 32'h8000_0000; // @@ Avalon-MM(Master側) ライトベースアドレス PRM_DIV = 0; // @@ シリアルクロック周波数設定 PRM_POL = 0; // @@ シリアルクロック極性設定 PRM_TAK = 0; // @@ シリアルデータ取り込みタイミング設定 // ++ [ 割り込み設定 ] ++ repeat( 5) @(PERIOD) PRM_CLR = 1; // @@ 割り込みクリア PRM_CLR = 0; PRM_MSK = 0; // @@ 割り込みマスク // ++ デバイスID読み出し // +++++++++++++++++++++++++++++++++++++++++++ FRAM.Device_ID[0] = 'h80; FRAM.Device_ID[1] = 'h40; FRAM.Device_ID[2] = 'h20; FRAM.Device_ID[3] = 'h10; FRAM.Device_ID[4] = 'h08; FRAM.Device_ID[5] = 'h04; FRAM.Device_ID[6] = 'h02; FRAM.Device_ID[7] = 'h01; FRAM.Device_ID[8] = 'hA5; repeat( 5) @(PERIOD); $display("\n===== Read Device ID ====="); PRM_ACS = 9; // @@ アクセスバイト数 (最大値:1,048,579) PRM_OTC = 0; // @@ 出力バイト数 (最大値:3) PRM_CMD = 'h9F; // @@ RAMコマンド PRM_ADD = 0; // @@ FRAMアドレス repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] PRM_ENB = 1; wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); repeat( 5) @(PERIOD); repeat( 5) @(PERIOD) PRM_CLR = 1; // @@ 割り込みクリア PRM_CLR = 0; repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] repeat(10) @(PERIOD); for(ei=0;ei<9;ei=ei+1)begin $display(" >>> Check : [%h] => %h , %h",ei[7:0],PMEM[ei],FRAM.Device_ID[ei]); if(PMEM[ei]!==FRAM.Device_ID[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ シリアル番号読み出し // +++++++++++++++++++++++++++++++++++++++++++ FRAM.Serial_No[0] = 'hFF^'h80; FRAM.Serial_No[1] = 'hFF^'h40; FRAM.Serial_No[2] = 'hFF^'h20; FRAM.Serial_No[3] = 'hFF^'h10; FRAM.Serial_No[4] = 'hFF^'h08; FRAM.Serial_No[5] = 'hFF^'h04; FRAM.Serial_No[6] = 'hFF^'h02; FRAM.Serial_No[7] = 'hFF^'h01; repeat( 5) @(PERIOD); $display("\n===== Read Serial No ====="); PRM_ACS = 8; // @@ アクセスバイト数 (最大値:1,048,579) PRM_OTC = 0; // @@ 出力バイト数 (最大値:3) PRM_CMD = 'hC3; // @@ RAMコマンド PRM_ADD = 0; // @@ FRAMアドレス repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] PRM_ENB = 1; wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); repeat( 5) @(PERIOD); repeat( 5) @(PERIOD) PRM_CLR = 1; // @@ 割り込みクリア PRM_CLR = 0; repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] repeat(10) @(PERIOD); for(ei=0;ei<8;ei=ei+1)begin $display(" >>> Check : [%h] => %h , %h",ei[7:0],PMEM[ei],FRAM.Serial_No[ei]); if(PMEM[ei]!==FRAM.Serial_No[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ 特殊セクタ読み出し // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<256;ei=ei+1) FRAM.Smem[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Special Sector Read ====="); PRM_ACS = 256+4-1; // @@ アクセスバイト数 (最大値:1,048,579) PRM_OTC = 4-1; // @@ 出力バイト数 (最大値:3) PRM_CMD = 'h4B; // @@ RAMコマンド PRM_ADD = 'h000000; // @@ FRAMアドレス repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] PRM_ENB = 1; wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); repeat( 5) @(PERIOD); repeat( 5) @(PERIOD) PRM_CLR = 1; // @@ 割り込みクリア PRM_CLR = 0; repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] repeat(10) @(PERIOD); for(ei=0;ei<256;ei=ei+1)begin $display(" >>> Check : [%h] => %h , %h",ei[7:0],PMEM[ei],FRAM.Smem[ei]); if(PMEM[ei]!==FRAM.Smem[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ 読み出し動作 // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<262144;ei=ei+1) FRAM.mem[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Read Data from Memory ====="); PRM_ACS = 262144+4-1; // @@ アクセスバイト数 (最大値:1,048,579) PRM_OTC = 4-1; // @@ 出力バイト数 (最大値:3) PRM_CMD = 'h03; // @@ RAMコマンド PRM_ADD = 'h000000; // @@ FRAMアドレス repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] PRM_ENB = 1; wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); repeat( 5) @(PERIOD); repeat( 5) @(PERIOD) PRM_CLR = 1; // @@ 割り込みクリア PRM_CLR = 0; repeat( 5) @(PERIOD); PRM_ENB = 0; // @@ 処理イネーブル [1→0:OFF 0→1:ON] repeat(10) @(PERIOD); for(ei=0;ei<262144;ei=ei+1)begin $display(" >>> Check : [%h] => %h , %h",ei[7:0],PMEM[ei],FRAM.mem[ei]); if(PMEM[ei]!==FRAM.mem[ei]) error = error + 1; end $display(" %m >> Error : %d",error); `endif // @@ // @@ Slave Mode (Read) // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ `ifdef SLAVE_MODE_READ repeat(20) @(PERIOD); MST_SLV = 1; // @@ Avalon-MM Master/Slave切替 [0:Master] // ++ [ 初期設定 ] ++ PRM_STA = 32'h8000_0000; // @@ Avalon-MM(Master側) ライトベースアドレス PRM_DIV = 15; // @@ シリアルクロック周波数設定 PRM_POL = 1; // @@ シリアルクロック極性設定 PRM_TAK = 3; // @@ シリアルデータ取り込みタイミング設定 // ++ [ 割り込み設定 ] ++ repeat( 5) @(PERIOD) PRM_CLR = 1; // @@ 割り込みクリア PRM_CLR = 1; PRM_MSK = 1; // @@ 割り込みマスク // ++ // ++ 制御レジスタの設定 // +++++++++++++++++++++++++++++++++++++++++++ REG_DATA.CNT.TOK = 0; // 取り込みタイミング REG_DATA.CNT.POL = 1; // シリアルクロック極性 REG_DATA.CNT.DIV = 0; // シリアルクロック分周 REG_DATA.ACS.ACS = 0; // アクセスバイト数 REG_DATA.OTC.OTC = 0; // 出力バイト数 REG_DATA.IRS.IRS = 1; // 割り込みステータス REG_DATA.IRM.IRM = 0; // 割り込みマスク REG_DATA.BAD.BAD = 0; // バッファリード/ライトアドレス REG_DATA.BDT.BDT = 0; // バッファリード/ライトデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.CNT,REG_DATA.CNT); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.ACS,REG_DATA.ACS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.OTC,REG_DATA.OTC); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRM,REG_DATA.IRM); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,REG_DATA.BAD); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // ++ デバイスID読み出し // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<9;ei=ei+1) FRAM.Device_ID[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Read Device ID ====="); REG_DATA.ACS.ACS = 9; // アクセスバイト数 REG_DATA.OTC.OTC = 0; // 出力バイト数 repeat( 5) @(PERIOD); WrCPU(REG_ADDR.ACS,REG_DATA.ACS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.OTC,REG_DATA.OTC); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000000); // バッファアドレス repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'h9F); // バッファデータ for(ei=0;ei<9;ei=ei+1) WrCPU(REG_ADDR.BDT,'hFF); // バッファデータ[リード領域の初期化] REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000001); // バッファアドレス for(ei=0;ei<9;ei=ei+1) begin repeat( 5) @(PERIOD); RdCPU(REG_ADDR.BDT,REG_DATA.BDT); $display(" >>> Check : [%h] => %h , %h",ei[23:0],REG_DATA.BDT.BDT,FRAM.Device_ID[ei]); if(REG_DATA.BDT.BDT!==FRAM.Device_ID[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ シリアル番号読み出し // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<8;ei=ei+1) FRAM.Serial_No[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Read Serial No ====="); REG_DATA.ACS.ACS = 8; // アクセスバイト数 REG_DATA.OTC.OTC = 0; // 出力バイト数 repeat( 5) @(PERIOD); WrCPU(REG_ADDR.ACS,REG_DATA.ACS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.OTC,REG_DATA.OTC); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000000); // バッファアドレス repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'hC3); // バッファデータ for(ei=0;ei<8;ei=ei+1) WrCPU(REG_ADDR.BDT,'hFF); // バッファデータ[リード領域の初期化] REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000001); // バッファアドレス for(ei=0;ei<8;ei=ei+1) begin repeat( 5) @(PERIOD); RdCPU(REG_ADDR.BDT,REG_DATA.BDT); $display(" >>> Check : [%h] => %h , %h",ei[23:0],REG_DATA.BDT.BDT,FRAM.Serial_No[ei]); if(REG_DATA.BDT.BDT!==FRAM.Serial_No[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ 特殊セクタ読み出し // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<256;ei=ei+1) FRAM.Smem[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Special Sector Read ====="); REG_DATA.ACS.ACS = 256+4-1; // アクセスバイト数 REG_DATA.OTC.OTC = 4-1; // 出力バイト数 repeat( 5) @(PERIOD); WrCPU(REG_ADDR.ACS,REG_DATA.ACS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.OTC,REG_DATA.OTC); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000000); // バッファアドレス repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'h4B); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'h00); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'h00); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'h00); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000004); // バッファアドレス for(ei=0;ei<256;ei=ei+1) begin repeat( 5) @(PERIOD); RdCPU(REG_ADDR.BDT,REG_DATA.BDT); $display(" >>> Check : [%h] => %h , %h",ei[23:0],REG_DATA.BDT.BDT,FRAM.Smem[ei]); if(REG_DATA.BDT.BDT!==FRAM.Smem[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ 読み出し動作 // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<262144;ei=ei+1) FRAM.mem[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Read Data from Memory ====="); begin : MemRead ei = 0; while( ei < 262144 ) begin REG_DATA.ACS.ACS = 2048+4-1; // アクセスバイト数 REG_DATA.OTC.OTC = 4-1; // 出力バイト数 repeat( 5) @(PERIOD); WrCPU(REG_ADDR.ACS,REG_DATA.ACS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.OTC,REG_DATA.OTC); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000000); // バッファアドレス repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'h03); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,ei[23:16]); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,ei[15: 8]); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,ei[ 7: 0]); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,'h00000004); // バッファアドレス repeat(2048) begin repeat( 5) @(PERIOD); RdCPU(REG_ADDR.BDT,REG_DATA.BDT); $display(" >>> Check : [%h] => %h , %h",ei[23:0],REG_DATA.BDT.BDT,FRAM.mem[ei]); if(REG_DATA.BDT.BDT!==FRAM.mem[ei]) error = error + 1; ei = ei + 1; end $display(" %m >> Error : %d",error); end end `endif // @@ // @@ Slave Mode (Write) // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ `ifdef SLAVE_MODE_WRITE repeat(20) @(PERIOD); MST_SLV = 1; // @@ Avalon-MM Master/Slave切替 [0:Master] // ++ 制御レジスタの設定 // +++++++++++++++++++++++++++++++++++++++++++ REG_DATA.CNT.TOK = 0; // 取り込みタイミング REG_DATA.CNT.POL = 1; // シリアルクロック極性 REG_DATA.CNT.DIV = 0; // シリアルクロック分周 REG_DATA.ACS.ACS = 0; // アクセスバイト数 REG_DATA.OTC.OTC = 0; // 出力バイト数 REG_DATA.IRS.IRS = 1; // 割り込みステータス REG_DATA.IRM.IRM = 0; // 割り込みマスク REG_DATA.BAD.BAD = 0; // バッファリード/ライトアドレス REG_DATA.BDT.BDT = 0; // バッファリード/ライトデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.CNT,REG_DATA.CNT); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.ACS,REG_DATA.ACS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.OTC,REG_DATA.OTC); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRM,REG_DATA.IRM); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BAD,REG_DATA.BAD); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // ++ ステータス レジスタの読み出し // +++++++++++++++++++++++++++++++++++++++++++ ei =0; repeat( 5) @(PERIOD); $display("\n===== Read Status Register ====="); REG_DATA.ACS.ACS = 1; WrCPU(REG_ADDR.ACS,REG_DATA.ACS); // アクセスバイト数 REG_DATA.OTC.OTC = 0; WrCPU(REG_ADDR.OTC,REG_DATA.OTC); // 出力バイト数 REG_DATA.IRM.IRM = 1; WrCPU(REG_ADDR.IRM,REG_DATA.IRM); // 割り込みマスク REG_DATA.IRS.IRS = 1; WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス クリア RdCPU(REG_ADDR.IRS,REG_DATA.IRS); $display(" >>> Read : %p",REG_DATA.IRS); REG_DATA.BAD.BAD = 0; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス REG_DATA.BDT.BDT ='h05; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル RdCPU(REG_ADDR.ENB,REG_DATA.ENB); while(REG_DATA.ENB.ENB===1) begin repeat(20) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); end REG_DATA.IRM.IRM = 0; WrCPU(REG_ADDR.IRM,REG_DATA.IRM); // 割り込みマスク 解除 REG_DATA.BAD.BAD = 1; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス repeat( 5) @(PERIOD); RdCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ $display(" >>> Check : [%h] => %h , %h",ei[23:0],REG_DATA.BDT.BDT,FRAM.realStatusRegister); if(REG_DATA.BDT.BDT!==FRAM.realStatusRegister) error = error + 1; $display(" %m >> Error : %d",error); // ++ シリアル番号の書き込み // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<8;ei=ei+1) PMEM[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Write Serial Number ====="); SetWREN(); repeat( 5) @(PERIOD); REG_DATA.ACS.ACS = 8; WrCPU(REG_ADDR.ACS,REG_DATA.ACS); // アクセスバイト数 REG_DATA.OTC.OTC = 8; WrCPU(REG_ADDR.OTC,REG_DATA.OTC); // 出力バイト数 REG_DATA.BAD.BAD = 0; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,'hC2); // バッファデータ for(ei=0;ei<8;ei=ei+1) WrCPU(REG_ADDR.BDT,PMEM[ei]); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); for(ei=0;ei<8;ei=ei+1) begin $display(" >>> Check : [%h] => %h , %h",ei[23:0],PMEM[ei],FRAM.Serial_No[ei]); if(PMEM[ei]!==FRAM.Serial_No[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ 特殊セクタの書き込み // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<256;ei=ei+1) PMEM[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Special Sector Write ====="); SetWREN(); repeat( 5) @(PERIOD); REG_DATA.ACS.ACS = 256+4-1; WrCPU(REG_ADDR.ACS,REG_DATA.ACS); // アクセスバイト数 REG_DATA.OTC.OTC = 256+4-1; WrCPU(REG_ADDR.OTC,REG_DATA.OTC); // 出力バイト数 REG_DATA.BAD.BAD = 0; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス REG_DATA.BDT.BDT = 'h42; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ REG_DATA.BDT.BDT = 'h00; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ REG_DATA.BDT.BDT = 'h00; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ REG_DATA.BDT.BDT = 'h00; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ for(ei=0;ei<256;ei=ei+1) WrCPU(REG_ADDR.BDT,PMEM[ei]); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); for(ei=0;ei<256;ei=ei+1) begin $display(" >>> Check : [%h] => %h , %h",ei[23:0],PMEM[ei],FRAM.Smem[ei]); if(PMEM[ei]!==FRAM.Smem[ei]) error = error + 1; end $display(" %m >> Error : %d",error); // ++ メモリ データの書き込み // +++++++++++++++++++++++++++++++++++++++++++ for(ei=0;ei<262144;ei=ei+1) PMEM[ei] = $random; repeat( 5) @(PERIOD); $display("\n===== Write Data to Memory ====="); begin : Write integer wi; ei = 0; wi = 0; while(ei < 262144 ) begin SetWREN(); repeat( 5) @(PERIOD); REG_DATA.ACS.ACS = 2048+4-1;WrCPU(REG_ADDR.ACS,REG_DATA.ACS); // アクセスバイト数 REG_DATA.OTC.OTC = 2048+4-1;WrCPU(REG_ADDR.OTC,REG_DATA.OTC); // 出力バイト数 REG_DATA.BAD.BAD = 0; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス REG_DATA.BDT.BDT = 'h02; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ WrCPU(REG_ADDR.BDT,ei[23:16]); // バッファデータ WrCPU(REG_ADDR.BDT,ei[15: 8]); // バッファデータ WrCPU(REG_ADDR.BDT,ei[ 7: 0]); // バッファデータ repeat(2048) begin WrCPU(REG_ADDR.BDT,PMEM[wi]); // バッファデータ wi = wi + 1; end REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); wait(CPU_IRQ===1'b1); $display(" >>> CPU_IRQ=1"); // 割り込み待ち repeat( 5) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル $display(" >>> Read : %p",REG_DATA.ENB); repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p",REG_DATA.IRS); repeat( 5) @(PERIOD); WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータスクリア repeat( 5) @(PERIOD); RdCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス $display(" >>> Read : %p - Clear",REG_DATA.IRS); repeat(2048) begin $display(" >>> Check : [%h] => %h , %h",ei[23:0],PMEM[ei],FRAM.mem[ei]); if(PMEM[ei]!==FRAM.mem[ei]) error = error + 1; ei = ei + 1; end end end $display(" %m >> Error : %d",error); // ++ ステータス レジスタ書き込み // +++++++++++++++++++++++++++++++++++++++++++ ei = 0; PMEM[ei] = 'hFF; repeat( 5) @(PERIOD); $display("\n===== Write Status Register ====="); SetWREN(); repeat( 5) @(PERIOD); REG_DATA.ACS.ACS = 1; WrCPU(REG_ADDR.ACS,REG_DATA.ACS); // アクセスバイト数 REG_DATA.OTC.OTC = 1; WrCPU(REG_ADDR.OTC,REG_DATA.OTC); // 出力バイト数 REG_DATA.IRM.IRM = 1; WrCPU(REG_ADDR.IRM,REG_DATA.IRM); // 割り込みマスク REG_DATA.IRS.IRS = 1; WrCPU(REG_ADDR.IRS,REG_DATA.IRS); // 割り込みステータス クリア RdCPU(REG_ADDR.IRS,REG_DATA.IRS); $display(" >>> Read : %p",REG_DATA.IRS); REG_DATA.BAD.BAD = 0; WrCPU(REG_ADDR.BAD,REG_DATA.BAD); // バッファアドレス REG_DATA.BDT.BDT ='h01; WrCPU(REG_ADDR.BDT,REG_DATA.BDT); // バッファデータ repeat( 5) @(PERIOD); WrCPU(REG_ADDR.BDT,PMEM[0]); // バッファデータ REG_DATA.ENB.ENB = 1; WrCPU(REG_ADDR.ENB,REG_DATA.ENB); // 処理イネーブル RdCPU(REG_ADDR.ENB,REG_DATA.ENB); while(REG_DATA.ENB.ENB===1) begin repeat(20) @(PERIOD); RdCPU(REG_ADDR.ENB,REG_DATA.ENB); end REG_DATA.IRM.IRM = 0; WrCPU(REG_ADDR.IRM,REG_DATA.IRM); // 割り込みマスク 解除 PMEM[ei] = PMEM[ei] & 'hCC; $display(" >>> Check : [%h] => %h , %h",ei[23:0],PMEM[0],FRAM.realStatusRegister); if(PMEM[0]!==FRAM.realStatusRegister) error = error + 1; $display(" %m >> Error : %d",error); `endif repeat(20) @(PERIOD); $finish(); end // -- // -- Clock生成 // ------------------------------------------------------------------- initial begin forever begin fork #(tpCPU_CLK) CPU_CLK = 1; #(tnCPU_CLK) CPU_CLK = 0; #(tcCPU_CLK) PERIOD = PERIOD+1; join end end initial begin forever begin fork #(tpSYS_CLK) SYS_CLK = 1; #(tnSYS_CLK) SYS_CLK = 0; #(tcSYS_CLK); join end end // -- // -- ターゲットのインスタンス // ------------------------------------------------------------------- wire dlyFRAM_CS_N; DlyBuf UnDlyFRAM_CS_N(.A(FRAM_CS_N),.Y(dlyFRAM_CS_N) ); wire dlyFRAM_SCLK; DlyBuf UnDlyFRAM_SCLK(.A(FRAM_SCLK),.Y(dlyFRAM_SCLK) ); wire dlyFRAM_MOSI; DlyBuf UnDlyFRAM_MOSI(.A(FRAM_MOSI),.Y(dlyFRAM_MOSI) ); wire dlyFRAM_MISO; DlyBuf UnDlyFRAM_MISO(.A(FRAM_MISO),.Y(dlyFRAM_MISO) ); NML_FRAMIF TARGET( .CPU_RST_N (CPU_RST_N ), // input wire CPU_RST_N , // @@ CPU I/F用 リセット .CPU_CLK (CPU_CLK ), // input wire CPU_CLK , // @@ CPU I/F用 クロック .SYS_RST_N (SYS_RST_N ), // input wire SYS_RST_N , // @@ システム動作用 リセット .SYS_CLK (SYS_CLK ), // input wire SYS_CLK , // @@ システム動作用 クロック .MST_SLV (MST_SLV ), // input wire MST_SLV , // @@ Avalon-MM Master/Slave切替 [0:Master] .PRM_ENB (PRM_ENB ), // input wire PRM_ENB , // @@ 処理イネーブル [1→0:OFF 0→1:ON] .PRM_DIV (PRM_DIV ), // input wire [ 3:0] PRM_DIV , // @@ シリアルクロック周波数設定 .PRM_POL (PRM_POL ), // input wire PRM_POL , // @@ シリアルクロック極性設定 .PRM_TAK (PRM_TAK ), // input wire [ 1:0] PRM_TAK , // @@ シリアルデータ取り込みタイミング設定 .PRM_ACS (PRM_ACS ), // input wire [20:0] PRM_ACS , // @@ アクセスバイト数 (最大値:1,048,579) .PRM_OTC (PRM_OTC ), // input wire [ 1:0] PRM_OTC , // @@ 出力バイト数 (最大値:3) .PRM_MSK (PRM_MSK ), // input wire PRM_MSK , // @@ 割り込みマスク .PRM_CLR (PRM_CLR ), // input wire PRM_CLR , // @@ 割り込みクリア .PRM_STA (PRM_STA ), // input wire [31:0] PRM_STA , // @@ Avalon-MM(Master側) ライトベースアドレス .PRM_CMD (PRM_CMD ), // input wire [ 7:0] PRM_CMD , // @@ RAMコマンド .PRM_ADD (PRM_ADD ), // input wire [23:0] PRM_ADD , // @@ FRAMアドレス .SAV_WEN (SAV_WEN ), // input wire SAV_WEN , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) ライトイネーブル .SAV_REN (SAV_REN ), // input wire SAV_REN , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リードイネーブル .SAV_ADD (SAV_ADD ), // input wire [ 5:0] SAV_ADD , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リード/ライトイネーブル .SAV_WDT (SAV_WDT ), // input wire [31:0] SAV_WDT , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) ライトデータ .SAV_WIT (SAV_WIT ), // output wire SAV_WIT , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) ウェイトリクエスト .SAV_RVL (SAV_RVL ), // output wire SAV_RVL , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リードデータイネーブル .SAV_RDT (SAV_RDT ), // output wire [31:0] SAV_RDT , // @@ [CPU_CLK↑同期] Avalon-MM(Slave側) リードデータ .MAV_WEN (MAV_WEN ), // output wire MAV_WEN , // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ライトイネーブル .MAV_ADD (MAV_ADD ), // output wire [31:0] MAV_ADD , // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ライトアドレス .MAV_BEN (MAV_BEN ), // output wire [ 3:0] MAV_BEN , // @@ [CPU_CLK↑同期] Avalon-MM(Master側) バイトイネーブル .MAV_WDT (MAV_WDT ), // output wire [ 7:0] MAV_WDT , // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ライトデータ .MAV_WIT (MAV_WIT ), // input wire MAV_WIT , // @@ [CPU_CLK↑同期] Avalon-MM(Master側) ウェイトリクエスト .CPU_IRQ (CPU_IRQ ), // output wire CPU_IRQ , // @@ [CPU_CLK↑同期] 割り込み信号 .MON_ENB (MON_ENB ), // output wire MON_ENB , // @@ [CPU_CLK↑同期] 動作モニタ [0:停止中 1:動作中] .FRAM_CS_N ( FRAM_CS_N ), // output reg FRAM_CS_N , // @@ [SYS_CLK↑同期] SPI チップセレクト .FRAM_SCLK ( FRAM_SCLK ), // output reg FRAM_SCLK , // @@ [SYS_CLK↑同期] SPI シリアルクロック .FRAM_MOSI ( FRAM_MOSI ), // output reg FRAM_MOSI , // @@ [SYS_CLK↑同期] SPI シリアル出力 .FRAM_MISO (dlyFRAM_MISO ), // input wire FRAM_MISO , // @@ [SYS_CLK↑同期] SPI シリアル入力 .FRAM_OUTE ( FRAM_OUTE ) // output reg FRAM_OUTE // @@ [SYS_CLK↑同期] SPI 出力イネーブル[1:出力 0:Hi-Z] ); reg FRAM_VDD = 0; initial begin #1; FRAM_VDD=1; end FRAM_SPI FRAM( .CSB (dlyFRAM_CS_N ), .SCK (dlyFRAM_SCLK ), .SI (dlyFRAM_MOSI ), .SO ( FRAM_MISO ), .WPB (1'b1 ), .VDD ( FRAM_VDD ) ); // -- // -- Task // ------------------------------------------------------------------- task WrCPU( input [31:0] Addr, input [31:0] Data ); reg Comp; begin Comp = 0; @(posedge CPU_CLK) begin SAV_WEN<=1; SAV_ADD<=Addr; SAV_WDT<=Data; end while( Comp == 0 ) begin @(posedge CPU_CLK) begin if( SAV_WIT===1'b0 ) begin SAV_WEN<=0; SAV_ADD<=0; SAV_WDT<=0; Comp<=1; end end #1; end end endtask task RdCPU( input [31:0] Addr, output [31:0] Data ); reg Comp; begin Comp = 0; @(posedge CPU_CLK) begin SAV_REN<=1; SAV_ADD<=Addr; end while( Comp == 0 ) begin @(posedge CPU_CLK) begin if( SAV_WIT===1'b0 ) begin SAV_REN<=0; SAV_ADD<=0; end if( SAV_RVL===1'b1 ) begin Data <= SAV_RDT; Comp <= 1; end end #1; end end endtask endmodule module DlyBuf #( parameter NsStep = 1, parameter PsStep = 1 ) ( input wire A , output wire Y ); wire [NsStep:0] SigNs; wire [PsStep:0] SigPs; assign SigNs[0] = A; generate genvar ins; if( NsStep != 0 ) begin for(ins=1;ins<=NsStep;ins=ins+1) begin DlyBufCoreNs UnDlyNs(.A(SigNs[ins-1]),.Y(SigNs[ins]) ); end end endgenerate assign SigPs[0] = SigNs[NsStep]; generate genvar ips; if( PsStep != 0 ) begin for(ips=1;ips<=PsStep;ips=ips+1) begin DlyBufCorePs UnDlyPs(.A(SigPs[ips-1]),.Y(SigPs[ips]) ); end end endgenerate assign Y = SigPs[PsStep]; endmodule module DlyBufCoreNs(input wire A, output wire Y); assign #(1.000) Y = A; endmodule module DlyBufCorePs(input wire A, output wire Y); assign #(0.001) Y = A; endmodule