10.ポストレイアウト遅延シミュレーション

論理合成した最大周波数で駆動してみましょう。

ところで、最初のTRYでは、Stratix、CYCLONEは通ったもののStratixUは走りませんでした。StratixUが走らなかったのは、H8プロジェクトに続いて2回目です。H8プロジェクトで行ったStratixU用の記述は既に実施済みだったので別なエラーです。

解析したところ(全ての信号が動いていなかったのですぐ分かりました)、sync_resetが次の記述で、StratixUでは HIGHになったままになってしまいました。(CYCLONEや、Stratixでは、問題なく遅延シミュレーションが通っています)


//sync_reset
      always @(posedge clock , negedge Async_Reset) begin
              if (!Async_Reset) sync_reset <=1'b1;
              else  sync_reset <=!Async_Reset;
      end


上記でも、問題ない記述の筈ですが、StratixUが通るように次のように書き換えました。

//Jul.29.2004
        always @(posedge clock ) begin
        //      if (!Async_Reset) sync_reset <=1'b1;
        /*      else*/  sync_reset <=!Async_Reset;
        end


この記述でStratixUで合成してみました。RAMは4KB です。156.1MHz(6.406ns)です。


ゲートシミュレーションのプロジェクトを作成します。

stratixii_atoms.vは、Quartusインストール環境にあります。同じドライブにないときは、COPYして持ってきます。

とりあえず、最大駆動周波数で駆動するために、テストベンチのクロック駆動部を次のように書き換えます。

`define CYCLE (6.406/2) //6.406
always #(`CYCLE) clock=~clock;


シミュレーションを行います。
下がそのログ(一回目のRUN)ですが、文字化けしています。Simulation自体は、進んでいるようなので、出力遅延が疑わしいです。


出力の遅延パスは、

 テストベンチCLOCK=>内部REGISTER=>内部REGISTER Q=>テストベンチ観測点

になります。時間がかかるIO遅延を往復することになりますから、156MHz駆動では、間に合っていない可能性が大です。
実際、遅延シミュレーション波形を見ると、下のようにやはり間に合っていません。
ステータスバーに 6.406ns(=T2-T1)が見えます。確かに、設定周波数になっています。このクロックPosedgeの前後で、波形ばバタついているのがわかります。つまり、Posedge読み込みに間に合っていないことが確認できました。


そこで、ゲートシミュレーションでは、下のソースのようにPosedge clockに読み込み遅延を3nsつけて読むことにします。

`timescale 1ns/1ps
`define ECHO_BACK
`define CYCLE (6.406/2) //6.406
`define DELAY_SIM
module yacc_test;
        reg clock=0;
        reg Reset=0;
        
        wire TXD;
        
`ifdef ECHO_BACK
        wire RXD=TXD;
`else   
        reg RXD=1;
`endif  

        wire [31:0] mem_data_w;
        wire mem_write;
        wire [15:0] mem_address;
        wire [11:0] PC;
        wire [31:0] IRD1;
        wire sync_reset;
        always #(`CYCLE) clock=~clock;



        initial begin
                Reset=0;
                #800 Reset=1;
        end     


 yacc cpu(.clock(clock),.Async_Reset(Reset),.MemoryWData(mem_data_w),
                  .MWriteFF(mem_write),
                  .data_port_address(mem_address),.RXD(RXD),.TXD(TXD),.IRD1(IRD1),
                  .sync_reset(sync_reset),.PC(PC));

   

   `define Print_Port_Address             12'hff0  //ATMEL Big Endian
      `define Print_CAHR_Port_Address 12'hff1
      `define Print_INT_Port_Address     12'hff2  //First ADDRESS
      `define Print_LONG_Port_Address  12'hff4  //First ADDRESS

        task Cprint;// String OUT until the byte 00 or xx detected with least Byte first and justified.
                integer i;
                begin :Block
                        i=0;
                        while (1) begin
                                if (char_buffer[i*8 +:8] ===8'h00 || char_buffer[i*8 +:8]===8'hxx) begin
                                                disable Block;
                                end     
                                $write("%c",char_buffer[i*8 +:8]);
                                i=i+1;  
                        end
                end
        endtask

   reg [0:639] char_buffer;
   integer  counter=0;    
   always @ (posedge clock ) begin
                `ifdef DELAY_SIM
                        #3;//
                `endif
            if ((mem_write === 1'b1)) begin 
    
                   if (mem_address==`Print_Port_Address) begin
                                if (mem_data_w[7:0]===8'h00) begin
                                        char_buffer[counter*8 +:8]=mem_data_w[7:0];
                                        if (char_buffer[0  +:8*7]==="$finish") begin
                                                        $stop;                          
                                                        
                                        end else if (char_buffer[0  +:8*5]==="$time") begin
                                                        $display("Current Time on Simulation=%d",$time);                                
                                                        
                                        end else  Cprint;//$write("%s",char_buffer);

                                        for (counter=0; counter< 80; counter=counter+1) begin
                                                char_buffer[counter*8 +:8]=8'h00;
                                        end
                                        counter=0;
                                
                                end else begin
                                        char_buffer[counter*8 +:8]=mem_data_w[7:0];
                                        counter=counter+1;
                                end
                   end
           else if (mem_address==`Print_CAHR_Port_Address) begin
                                $write("%h ",mem_data_w[7:0]);
                   end else if (mem_address==`Print_INT_Port_Address) begin
                                $write("%h ",mem_data_w[15:0]);//Little Endian 
                   end else if (mem_address==`Print_LONG_Port_Address) begin
                                $write("%h ",mem_data_w[31:0]);//Big Endian
                   end 
        end //if
   end //always


endmodule


こうすると2回目のRUNのとおり、SETUP/HOLD TIMEが十分あるので、文字化けはなくなりました。

筆者のマシン(Athron1.2GHz)で6時間程、走らせるとやっとTEST終了です。7月30日2004現在、StartixUボードは、未だないですが、合成後のポストレイアウトゲートシミュレーションでも、156MHzで動くことが、検証できました。


なお、Stratix、CYCLONE共、同様の手順で動作確認を行いました。

Xilinx Gate Simulation

Dual Portのメモリ衝突エラーメッセージが頻発してしまい、コンソール出力を確認することが困難です。
実際上は、同期クロックエッジしか使用していないため、YACCでは無害ですが、CoregenでWarningをDisableにしても変わりません。駆動周波数は、25MHzです。


そこで、やむを得ず、RAMのPRIMITIVE記述を以下のように変更しました。
parameter SIM_COLLISION_CHECK = "NONE";//All ORIG TAK Apr.12.2005
これで、次のようにコンソール出力を確認することができます。(なお、最初のSDFメッセージは、電源On時のシミュレータ過渡状態によるものですので無視します。)


StratixU16KB 版では、駆動周波数を最大駆動周波数の165MHzにして走らせました。


Cycloneでは、104MHzです。