FC2カウンター FPGAの部屋 DDR SDRAMコントローラの高度なシミュレーション3
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

DDR SDRAMコントローラの高度なシミュレーション3

”DDR SDRAMコントローラの高度なシミュレーション2”のVerilogコードの差分をたっくさんの許可が出たのでブログに載せておこうと思う。
最初にメインのinitial文。

    reg  [31:0] read_fifo [0: 2**23-1];//24bit fifo
    reg [23:0]  seed_address,write_temp_address,read_temp_address;
    integer seed_data,write_temp_data,read_temp_data;
    integer burst_words,burst_words_seed;
    integer burst_write_words, burst_write_words_seed;
    integer test_counter;
    integer burst_read_cmd_end_flag;
    initial begin
        $timeformat(-9,1,"nsec",8);
        //準備ができるまで待つ
        initial_wait;
        
        //シングルライト/リード
        check_random_single_write_read(10);
        //インクリメンタルチェック
        check_incremental_single_write_read(10);
        
        //バースト ライト/リード 固定アドレス
        burst_check_fixed_pattern(0,10,32'h5555_5555);//256まではOK
        burst_check_fixed_pattern(0,258,32'hAAAA_AAAA);//256まではOK
    //    $stop;
        //バースト ライト/リード ランダムアドレス
        seed_address=1<<2;
        seed_data=1;
        write_temp_address=seed_address;
        write_temp_data=seed_data;
        read_temp_address=seed_address;
        read_temp_data=seed_data;
        burst_words_seed=1;
        burst_write_words_seed = burst_words_seed;
        burst_words=burst_words_seed;
        test_counter=0;
        `define Check_Max_burst_words 20
        sequential_burst_write_random(write_temp_address,write_temp_data,burst_words);
        burst_write_words = burst_words;
        repeat(100000) begin
                 
            $display("Start burst write random burst_words=%d%t",burst_words,$time);
            // burst_write_random(write_temp_address,write_temp_data,burst_words);
                
            //$display("Start burst read random %t",$time);
            // burst_read_random(read_temp_address,burst_words);
            // burst_read_check_random(read_temp_data ,burst_words);
            
            fork
                begin
                    sequential_burst_read_random(read_temp_address,burst_words);
                    sequential_burst_read_check_random(read_temp_data ,burst_words);
                end
                begin
                    wait(burst_read_cmd_end_flag==1);
                    wait(burst_read_cmd_end_flag==0); // バーストリードのFIFO書き込みの終了を検出
                    
                    burst_write_words_seed=lfsr8(burst_write_words_seed);
                    
                    if(burst_write_words_seed> `Check_Max_burst_words) begin
                        burst_write_words=burst_write_words_seed%`Check_Max_burst_words;
                        if (!burst_write_words) burst_write_words=1;
                    end
                    sequential_burst_write_random(write_temp_address,write_temp_data,burst_write_words); // 次のライト
                end
            join
            
            test_counter=test_counter+1;
            if (test_counter%100==0) $display("Pass %d",test_counter);
            burst_words = burst_write_words;
        end
        
        #1000000    $finish;
    end


sequential_burst_write_random、sequential_burst_read_random、sequential_burst_read_check_random の各taskを新しく作った。バーストアクセスのチェック用だ。
ライト用のburst_write_words, burst_write_words_seedを宣言する。次のシードの計算をライトのみ行い、次のライトとDDR SDRAMから出てきたリードデータをFIFOに入れるプロセスとを並列に実行するためだ。これはループの最後でリード用(元)の変数に代入する。
最初にsequential_burst_write_randomを実行しておいて、fork join で、sequential_burst_read_random、sequential_burst_read_checkと次のsequential_burst_write_randomを並列に実行する。ただし、DDR SDRAMコントローラへリードのコマンドを入力するプロセスが終了してから、sequential_burst_write_randomを実行しないとバグるため、wait(burst_read_cmd_end_flag==1); wait(burst_read_cmd_end_flag==0);で待たせている。
次にsequential_burst_write_random、sequential_burst_read_random、sequential_burst_read_check_random の各taskのVerilogソースを示す。

    task sequential_burst_write_random(inout integer seed_address,seed_data ,input integer counts);
        integer counter;
        integer address;
        begin
            
            //assert(read_fm_host==0);
            //ライトコマンドをcounts分送出
            counter=0;
            address = seed_address;
            seed_address=get_next_random_address(seed_address);
            
            repeat(counts) begin
    
                @(negedge clk_out);
                if (fifo_full_fm_controller) begin
                    write_fm_host=0;
                    wait(!fifo_full_fm_controller);
                    @(negedge clk_out);
                end
                write_fm_host=1;
                input_data_fm_host=seed_data;
                address_fm_host   =address;
                seed_data=$random(seed_data);
                address = address + 2;
                
                counter=counter+1;
            end    
            @(negedge clk_out);
            write_fm_host=0;
            //ライトコマンド送出終わり
        end    
    endtask        

        task sequential_burst_read_check_random(inout integer seed_data,input integer counts);
        integer counter;
        begin
            counter=0;
            
            repeat(counts) begin
                
                if (read_fifo[counter] !==seed_data) begin
                    $display("Error Detected burst_read_check_random %t %h %h ",$time,read_fifo[counter],seed_data);
                    $stop;
                end
                seed_data=$random(seed_data);
                counter=counter+1;
            end    
            
        end    
    endtask        
    
    task sequential_burst_read_random(inout integer seed_address,input integer counts);
        integer send_counter,read_counter;    
        integer address;
        begin
            send_counter=0;
            //assert(read_fm_host==0);
            //リードコマンドをcounts分送出
            //assert(!read_valid_fm_controller);
            fork//コマンドを送っている間にもReadValidは来るので送信と受信は、平行プロセスでなければならない。
                begin
                    burst_read_cmd_end_flag = 1;
                    address = seed_address;
                    seed_address=get_next_random_address(seed_address);
                    
                    repeat(counts) begin
    
                        @(negedge clk_out);//Mar.6.2008 clk_outに変更
                        if (fifo_full_fm_controller) begin
                            read_fm_host=0;
                            wait(!fifo_full_fm_controller);
                            @(negedge clk_out);
                        end
                        read_fm_host=1;
                        address_fm_host=address;
                        address = address+2;
                        send_counter=send_counter+1;
                    end    
                    @(negedge clk_out);
                    read_fm_host=0;
                //リードコマンド送出終わり
                    burst_read_cmd_end_flag = 0;
                end
                
               //リードデータをcounts分読み込む
                begin
                    read_counter=0;
                    wait(send_counter !==0);//Mar.6.2008 Timeout Check のため
                    repeat(counts) begin
    
                        @(negedge clk_out);//Read 読み込みは、100MHzで来るので100MHzで受ける
                        if (!read_valid_fm_controller) begin
                            time_out_check_read_valid(counts);//Mar.6.2008 タイムアウトチェック追加
                            //wait(read_valid_fm_controller);
                            //@(negedge clk_out);//Read 読み込みは、100MHzで来るので100MHzで受ける
                        end
                        read_fifo[read_counter]=output_data_fm_controller;
                        read_counter=read_counter+1;        
                    end
                end    
            join
            
        end
    endtask


ちなみにsequential_burst_read_check_randomはburst_read_check_randomと同一です。
  1. 2008年03月14日 18:15 |
  2. DDR SDRAMコントローラ
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/756-eaa754ee
この記事にトラックバックする(FC2ブログユーザー)