デジタルIC手引きコード-○○社筆記試験問題(シリアル・パラレル変換制御)

 序文: 

        このコラムは、デジタル フロントエンドの秋採用者向けに、頻繁に行われるペン インタビューの手引きコード質問を記録することを目的としており、このコラムのすべての記事には原理分析、コードと波形が提供されており、すべてのコードは私自身によって検証されています。

ディレクトリは次のとおりです。

1. デジタルICハンドティアコード分周器(任意の偶数分周)

2. デジタル IC ハンドティアコード分周器 (任意の奇数分周)

3. デジタル IC ハンドティアコード分周器 (任意の 10 進分周)

4.デジタルICハンドティアリングコード - 非同期リセットと同期リリース

5.デジタルICハンドティアコード - エッジ検出(立ち上がりエッジ、立ち下がりエッジ、ダブルエッジ)

6. デジタルICハンドティアリングコード列検出(ステートマシン書き込み方式)

7. デジタルICハンドティアリングコード列検出(シフトレジスタ書き込み方式)

8. デジタルICティアリングコード - 半加算器、全加算器

9. デジタル IC ハンド ティアリング コード - シリアルからパラレル、パラレルからシリアル

10.デジタルICハンドティアリングコード-データビット幅変換器(幅-狭幅、狭幅変換)

11. デジタル IC ハンド ティアリング コード - 有限状態マシン FSM - 飲料マシン

12.デジタルICハンドティアコード - ハンドシェイク信号(READY-VALID)

13. デジタル IC ハンド ティアリング コード - 水ハンドシェイク (ハンドシェイクを使用してパイプラインの中断と背圧の問題を解決します)

14. デジタル IC ハンド テアリング コード - Telink マイクロ筆記試験問題

15. デジタル IC 手引きコード - Pingtouge 技術最終面手引き本当の質問

16.デジタルICマニュアルティアリングコード-Zhaoyiイノベーション筆記試験実際の質問

17. デジタル IC ハンド ティアリング コード - Espressif Technology 筆記試験実際の問題 (4 回の頻度)

18. デジタル IC ティアリング コード - デュアルポート RAM (デュアルポート RAM)

        ...継続的に更新

ハンドテアリング コードに関するその他の質問については、 デジタル IC ハンドテアリング コード - 質問バンクにアクセスしてください。


目次

トピックの説明

問題解決のアイデア

コード

テストベンチ

出力波形


トピックの説明

        データはシリアル変換されて処理され、シリアル 3780 ビットが入力され、各データは 1 クロック サイクルを占有し、入力は合計 3780 クロックを占有し、63 ビットをパラレルに出力する必要があり、合計 60 クロックが必要となります。タイミング図は次のとおりです: 1 クロックは 0、60、...、3720 をパラレルに出力し、2 番目のクロックはバス全体として 1、61、... 3721 としてパラレルに出力し、60 番目のクロックをパラレルに出力します。クロック出力 59, 119,... 3779 inParallel 注意: 各パラレル出力は 1 クロック サイクルのみを占有し、60 クロック サイクルで出力が完了します。出力と入力の間の相対遅延関係は任意です。

問題解決のアイデア

        この問題は一見非常に簡単で、シリアルからパラレルへの変換だけで済むように見えますが、実際には 1 ビットのデータの位置の問題が含まれており、それだけでなく、書かれたコードが「ワンタイム」でない場合、連続送信や断続的な送信のテストに耐えることができますが、すべての状況を考慮してコードを記述する必要があります。

        タイトルの意味を改めて考えてみますと、シリアルパラレル変換を実現し、1サイクルあたり1ビットのデータを入力し、3780サイクル以内に3780個の1ビットデータの入力を完了するというタイトルです。パラレル出力はすべてのシリアル入力が完了した後に実行されるため、3780 個のシリアル入力を保存する必要があります。これは RAM またはレジスタに直接保存できます。パラレル出力、各出力 63 ビット、合計出力 60 サイクル、60*63 ビット = 3780 ビット。

        ここで重要なのは、パラレル出力の隣接ビットが 0、60、120...; 1、61、121...; とジャンプしているため、パラレル出力とシリアル出力の間のマッピング関係を見つけることが特に重要です。入力。60*63=3780 の 1 次元配列 data_store を使用して、入力シリアル データを保存できます。私のアイデアは、アドレス addr を使用して、1 次元配列 data_store に格納されている位置に毎回インデックスを付け、63 サイクルごとにループし、合計 60 回のループになるというものです。 1 次元配列で、データと位置はそれぞれ 59、119、179、...、3719、3779 に格納されます。63 サイクルごとに (63 ビットのデータを保存した後)、1 次元配列は右に 1 ビット (左側に上位ビット、右側に下位ビット) シフトされます。このようにして、62 回のシフトの後、最初に書き込まれた単一ビット データは最下位ビットにシフトされ、先頭の位置 62 に書き込まれたビットは位置 0 にシフトされ、先頭の位置 3779 に書き込まれたビットは、位置 3717 にシフトされます。最後に、60 回のループの後、3780 個のシングル ビット データが入力され、高ビット データを出力し、output_valid 出力有効信号を High に引き上げ、同時に 1 サイクルに 1 回 63 ビットを出力し、63 ビットを 60 回出力します。シリアルからパラレルへの変換が完了します。


reg [5:0] shiftcount;
always @(posedge clk)begin
    if(data_in_ena && loop_row == 6'd0)begin
        data_store[addr] <= serial_data;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
        data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times   60bit shift one times 
        shiftcount <= shiftcount + 1'b1;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
        data_store[addr] <= serial_data;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        addr <= 12'd62;
        shiftcount <= 6'd0;
    end
    else if(data_in_ena && count_row < 59)begin
        addr <= 63*count_row+12'd125;  //addr belongs to {62,125,188,...,3779}  
    end
    else if(data_in_ena && count_row == 59)begin
        addr <= 12'd62;
    end
end

コード

module serial_to_parallel (
    input               clk             ,
    input               rstn            ,
    input               serial_data     ,
    input               data_in_ena     ,

    output      [62:0]  parallel_data   ,
    output  reg         data_out_ena
);

reg [3779:0] data_store;
reg [11:0] addr;
reg [62:0] parallel_data_reg;

reg [5:0] count_column,count_row; //one column is once parallel_data
reg [5:0] loop_column,loop_row;

reg [5:0] output_count;
reg output_valid;

always @(posedge clk)begin     //one loop ,save 63 bits data, so count_column belongs to [0,62]
    if(!rstn)begin
        count_column <= 6'd0;
    end
    else if(data_in_ena && count_column < 6'd62)begin
        count_column <= count_column + 1'b1;
    end
    else if(data_in_ena && count_column == 6'd62)begin
        count_column <= 6'd0;
    end
end

always @(posedge clk)begin     //count_row belongs to [0,59]
    if(!rstn)begin
        count_row <= 6'd0;
    end
    else if(data_in_ena && count_row < 6'd59)begin
        count_row <= count_row + 1'b1;
    end
    else if(data_in_ena && count_row == 6'd59)begin
        count_row <= 6'd0;
    end
end


always @(posedge clk)begin      //loop_column belongs to [0,59]
    if(!rstn)begin
        loop_column <= 6'd0;
    end
    else if(count_column == 6'd62 && loop_column < 6'd59)begin
        loop_column <= loop_column + 1'b1;
    end
    else if(count_column == 6'd62 && loop_column == 6'd59)begin
        loop_column <= 6'd0;
    end
end

always @(posedge clk)begin      //loop_row belongs to [0,62]
    if(!rstn)begin
        loop_row <= 6'd0;
    end
    else if(count_row == 6'd59 && loop_row < 6'd62)begin
        loop_row <= loop_row + 1'b1;
    end
    else if(count_row == 6'd59 && loop_row == 6'd62)begin
        loop_row <= 6'd0;
    end
end


reg [5:0] shiftcount;
always @(posedge clk)begin
    if(data_in_ena && loop_row == 6'd0)begin
        data_store[addr] <= serial_data;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
        data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times   60bit shift one times 
        shiftcount <= shiftcount + 1'b1;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
        data_store[addr] <= serial_data;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        addr <= 12'd62;
        shiftcount <= 6'd0;
    end
    else if(data_in_ena && count_row < 59)begin
        addr <= 63*count_row+12'd125;  //addr belongs to {62,125,188,...,3779}  
    end
    else if(data_in_ena && count_row == 59)begin
        addr <= 12'd62;
    end
end

//parallel output
genvar i ;
generate
    for (i=0;i<=59;i=i+1)begin
        always @(posedge clk)begin
            if(output_valid == 1'b1)begin
                case(output_count)
                    i:parallel_data_reg <= data_store[i*63+62:i*63];
                endcase
            end
        end
    end
endgenerate

always @(posedge clk)begin
    if(!rstn)begin
        output_valid <= 1'b0;
    end
    else if(count_column == 6'd62 && loop_column == 6'd59)begin
        output_valid <= 1'b1;
    end
    else if(output_valid == 1'b1 && output_count == 6'd59)begin
        output_valid <= 1'b0;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        output_count <= 6'd0;
    end
    else if(output_valid == 1'b1 && output_count < 6'd59)begin
        output_count <= output_count + 1'b1;
    end
    else begin
        output_count <= 6'd0;
    end
end

always @(posedge clk)begin
    data_out_ena <= output_valid; //one beat late
end

assign parallel_data = parallel_data_reg;

endmodule

テストベンチ

module serial_to_parallel_tb();

reg clk,rstn;
reg serial_data,data_in_ena;

wire [62:0] parallel_data;
wire  data_out_ena;

always #5 clk = ~clk;
initial begin
    clk <= 1'd0;
    rstn <= 1'd0;
    serial_data <= 1'b1;
    #16
    rstn <= 1'b1;
    forever begin
        repeat(3780)begin
            #10
            serial_data <= serial_data + 1'b1;
            data_in_ena <= 1'b1;
        end
        repeat(60)begin
            #10
            data_in_ena <= 1'b0;
        end
    end
end
initial begin
    #100000
    $finish();
end

//dump fsdb 
initial begin 
    $fsdbDumpfile("serial_to_parallel.fsdb");
    $fsdbDumpvars(0);
end 

serial_to_parallel u_serial_to_parallel(
    .clk            (clk)               ,  
    .rstn           (rstn)              ,
    .serial_data    (serial_data)       ,
    .data_in_ena    (data_in_ena)       ,

    .parallel_data  (parallel_data)     ,
    .data_out_ena   (data_out_ena)
);

endmodule

出力波形

        バックツーバック伝送をサポートしており、シングルビットデータを 3780 サイクルで入力し、その後有効信号を入力して 60 サイクル間 Low にプルされ、このとき出力の valid 信号は High にプルされ、63 ビットパラレルになりますデータは60サイクル出力されます。


 ハンドテアリング コードに関するその他の質問については、 デジタル IC ハンドテアリング コード - 質問バンクにアクセスしてください。

おすすめ

転載: blog.csdn.net/qq_57502075/article/details/127838432