同期ビデオ信号と内部ストリーミングバス間の簡易IF実装

# はじめに
　FPGA内で同期ビデオ信号をAvalon-STやAXI4-Streamといったストリームバスに変換するための簡易的な実装例です。IntelのFPGA向けには、様々な画像処理に対応したIP群（VIP)がラインナップされており、その中に同期ビデオ信号をAvalon-STに変換するIPも用意されています。このIPは豊富な機能を持っていますが、その分ある程度パラメータやレジスタの設定が必要です。

　評価ボード上で実験的な画像入出力回路を動かそうとする場合、本格的なVIPを使うほどではないケースも多いかと思います。本記事はこうした用途に向けた、同期ビデオ信号変換回路の簡易な実装例になります。なお、あくまで評価等を目的としたものなので、動作仕様としてはかなり限定したものになっています。その点、事前にご了解いただけましたら幸いです。なお、今回実機検証は下記デバイスにて実施いたしましたが、特にデバイス特有な機能に依存しているところはありませんので、他のIntel FPGAにも実装可能です。

　あと、テストの際のストリームクロックは160MHzにしていますが、これに特別な意図はありません。とりあえず、ビデオクロックより高速な非同期の周波数にしておきたかっただけです。Cyclone Vであれば180MHz程度までは動くと思われます。

# 開発環境

| 項目　　　　　　　|名称　　　　　　　　　　　　　　　　　　　　　　　　|
|:--------------------|:-------------------------------------------|
| 記述言語　　　　　| Verilog　　　　　　　　　　　　　　　　　　　　　|
| 検証ツール　　　　| ModelSim Altera Starter Edition　　　　　　　　|
| 合成ツール　　　　| Quartus Prime ver19.1　　　　　　　　　　　　　　|
| ターゲットFPGA　　| Cyclone V シリーズ 5CSXFC5D6F31　　　　　　　　|

# 画像仕様
 
| 項目　　　　　　　|仕様　　　　　　　　　　　　　　　　　　　　　　　　|
|:--------------------|:-------------------------------------------|
| 画像サイズ　　　　| 1920 x 1080　　　　　　　　　　　　　　　　　　　|
| スキャン方式　　　| progressive　　　　　　　　　　　　　　　　　　　|
| ビデオクロック　　　| 148.5MHz　　　　　　　　　　　　　　　　　　　　|
| ストリームクロック　| 160MHz　　　　　　　　　　　　　　　　　　　　　|


# 信号端子
#### 同期ビデオ信号

| 信号名　　　　　　　|機能　　　　　　　　　　　　　　　　　　　|
|:--------------------|:-------------------------------------|
| vclk　　　　| ビデオクロック　　　　　　　　　　　　　　　　|
| vsync_b　　　| 垂直同期(負論理)　　　　　　　　　　　　　　　|
| hsync_b　　　| 水平同期(負論理)　　　　　　　　　　　　　　　　|
| data_en　| 画像有効フラグ(正論理)　　　　　　　　　　　　　　　　|
| vdata[23:0]　| 画像データ(RGB888)　　　　　　　　　　　　　　　　　|

#### AvalonST信号

| 信号名　　　　　　　|機能　　　　　　　　　　　　　　　　　　　|
|:--------------------|:-------------------------------------|
| av_start　　　　| スタートフラグ　　　　　　　　　　　　　　　　|
| av_end　　　| エンドフラグ　　　　　　　　　　　　　　　|
| av_data[31:0]　　　| ストリームデータ　　　　　　　　　　　　　　　　|
| av_valid　| ハンドシェイク(要求)　　　　　　　　　　　　　　　　|
| av_ready　| ハンドシェイク(許可)　　　　　　　　　　　　　　　　　|

#### AXI4-stream信号

| 信号名　　　　　　　|機能　　　　　　　　　　　　　　　　　　　|
|:--------------------|:-------------------------------------|
| ax_tuser　　　　| 先頭データフラグ　　　　　　　　　　　　　　　　|
| ax_tlast　　　| ラインエンドフラグ　　　　　　　　　　　　　　　|
| ax_tdata[31:0]　　　| ストリームデータ　　　　　　　　　　　　　　　　|
| ax_tvalid　| ハンドシェイク(要求)　　　　　　　　　　　　　　　　|
| ax_tready　| ハンドシェイク(許可)　　　　　　　　　　　　　　　　　|

#### System信号

| 信号名　　　　　　　|機能　　　　　　　　　　　　　　　　　　　|
|:--------------------|:-------------------------------------|
| aclk　　　　| ストリームクロック　　　　　　　　　　　　　　　　|
| reset_b　　　| システムリセット　　　　　　　　　　　　　　　|
| st_sel　　　| ストリームプロトコル選択　　　　　　　　　　　　　　　|
| conv_en　| 変換転送イネーブル　　　　　　　　　　　　　　　　|

# 動作概要
　出力するストリームバスは、AXI4-streamとAvalonSTの2つが選択できます。具体的には、st_sel="0"のときAvalonST側、"1"のときAXI4-streamが有効になります。

　システムリセットを解除し、conv_enを有効("1")にすると、同期ビデオ信号側は次のフレームからdata_enで示される有効データをそのまま非同期FIFOに書き込みます。ストリームバス側は、data_enをアサートした後、非同期FIFOのemptyフラグがデアサート状態になると、データ読み出しのステートになり、データの転送を開始します。この時、最初に読み出されたデータが自動的にフレームの先頭データとして取り扱われます。

　AXI4-stream側の動作としてはこの先頭データと同時にax_tuserを"1"にして出力します。以降、FIFO内にデータが存在すればax_tvalidを"1"にしつつ順次データを出力します。なお、1920データごとに1行の最後のフラグとしてax_tlastを"1"にして出力します。

　一方、AvalonST側はプロトコルとして、画像データの転送を開始する前にコントロールパケットを出力する必要があります。そのため、FIFOにデータが書き込まれると、まず、画像仕様に準じたフォーマットのコントロールパケットを出力し、それに引き続いて画像データパケットを出力します。また、こちらも1920データ出力するごとにav_endを"1"にして出力します。なお、AvalonSTのready信号には、Latencyとallowanceというプロパティが存在しています。通常、これらのプロパティの値は1になっていると思われますが、一応、本実装ではRTL内のパラメータ設定で規定の0から8に対応出来るようにしています。以下に概略タイミングと簡単なブロック図を示します。

# 概略タイミング
![timing_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171221/1a081818-b923-ff90-5b3b-7625a1caa721.png)

# ブロック図

![fpga_block.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171221/99546cb3-82b0-76c5-b1d7-c96c276cbc92.png)

# RTLソース

```vid_ax_av.v
`timescale 1ns / 1ps

module  vid_av_ax   (
    input           aclk        ,
    input           vclk        ,
    input           conv_en     ,
    input           aresetn     ,

    output  [31:0]  ax_tdata    ,
    output          ax_tvalid   ,
    output          ax_tuser    ,
    output          ax_tlast    ,
    input           ax_tready   ,

    output  [31:0]  av_data     ,
    output          av_valid    ,
    output          av_start    ,
    output          av_end      ,
    input           av_ready    ,

    input   [23:0]  vdata       ,
    input           data_en     ,
    input           hsync_b     ,
    input           vsync_b     ,

    input           st_sel      
);

//  parameter
    parameter   [31:0]  p_ctr_start     =   32'h0000000f,
                        p_vid_start     =   32'h00000000,
                        p_ctr_interlace =   32'h00000007;
    parameter   [11:0]  p_h_size        =   12'd1920,
                        p_v_size        =   12'd1080,
                        p_h_size1       =   p_h_size - 12'd1,
                        p_h_size2       =   p_h_size - 12'd2,
                        p_v_size1       =   p_v_size - 12'd1;
    parameter   [3:0]   p_ava_allowance =   4'h0,   //min0 max8
                        p_ava_latency   =   4'h0;   //min0 max8
    parameter   [2:0]   p_ctr_cnt_max   =   3'd4,
                        p_ctr_cnt_max1  =   p_ctr_cnt_max - 3'd1,
                        p_ctr_cnt_max2  =   p_ctr_cnt_max - 3'd2;
    parameter   [1:0]   p_vid_idle      =   2'b00,
                        p_vid_wait      =   2'b01,
                        p_vid_write     =   2'b11,
                        p_a_idle        =   2'b00,
                        p_a_wait        =   2'b01,
                        p_a_ctr         =   2'b10,
                        p_a_read        =   2'b11,
                        p_move_wait     =   2'b00,
                        p_to_ctr        =   2'b01,
                        p_to_rd         =   2'b11;
    parameter   [0:0]   p_ax_mode       =   1'b1,
                        p_av_mode       =   1'b0;

//  wire
    wire    [3:0]   w_ava_allow     ;
    wire            w_ava_alw_rdy   ;
    wire            w_aclr_b        ;
    wire            w_aclr          ;
    wire            w_read_en       ;
    wire            w_write_en      ;
    wire    [31:0]  w_data_out      ;
    wire            w_empty         ;
    wire            w_empty_b       ;
    wire            w_full          ;
    wire            w_ready         ;
    wire    [3:0]   w_ava_late      ;
    wire            w_ava_valid_o   ;
    wire            w_ava_end_o     ;
    wire            w_ava_start_o   ;
    wire    [31:0]  w_ava_data_o    ;

//  reg
    reg     [7:0]   r_ava_alw_rdy   ;
    reg             r_conven_v1     ;
    reg             r_conven_v2     ;
    reg             r_vsync_b_1     ;
    reg             r_vsync_b_2     ;
    reg             r_hsync_b       ;
    reg             r_en            ;
    reg     [31:0]  r_data_in       ;
    reg             r_conven_a1     ;
    reg             r_conven_a2     ;
    reg     [1:0]   r_vid_state     ;
    reg     [1:0]   r_a_state       ;
    reg     [2:0]   r_ava_ctr_cnt   ;
    reg     [1:0]   r_state_move    ;
    reg             r_read_en       ;
    reg     [10:0]  r_a_hcnt        ;
    reg     [10:0]  r_a_vcnt        ;
    reg             r_tval          ;
    reg             r_tlast         ;
    reg             r_tuser         ;
    reg     [31:0]  r_tdata         ;
    reg             r_ava_start     ;
    reg             r_ava_end       ;
    reg             r_ava_valid     ;
    reg     [31:0]  r_ava_data      ;
    reg     [7:0]   r_ava_late_val  ;
    reg     [7:0]   r_ava_late_start;
    reg     [7:0]   r_ava_late_end  ;
    reg     [31:0]  r_ava_data1     ;
    reg     [31:0]  r_ava_data2     ;
    reg     [31:0]  r_ava_data3     ;
    reg     [31:0]  r_ava_data4     ;
    reg     [31:0]  r_ava_data5     ;
    reg     [31:0]  r_ava_data6     ;
    reg     [31:0]  r_ava_data7     ;
    reg     [31:0]  r_ava_data8     ;

//  AvalonST allowance
    assign  w_ava_allow =   p_ava_allowance ;

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_alw_rdy   <=  8'h00   ;
        end
        else begin
            r_ava_alw_rdy   <=  {r_ava_alw_rdy[6:0],av_ready}   ;
        end
    end

    assign  w_ava_alw_rdy   =   (w_ava_allow == 4'h0)?  av_ready :
                                (w_ava_allow == 4'h1)?  av_ready | r_ava_alw_rdy[0] :
                                (w_ava_allow == 4'h2)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] :
                                (w_ava_allow == 4'h3)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] | r_ava_alw_rdy[2]   :
                                (w_ava_allow == 4'h4)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] | r_ava_alw_rdy[2] | r_ava_alw_rdy[3] :
                                (w_ava_allow == 4'h5)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] | r_ava_alw_rdy[2] | r_ava_alw_rdy[3] | r_ava_alw_rdy[4] :
                                (w_ava_allow == 4'h6)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] | r_ava_alw_rdy[2] | r_ava_alw_rdy[3] | r_ava_alw_rdy[4] | r_ava_alw_rdy[5] :
                                (w_ava_allow == 4'h7)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] | r_ava_alw_rdy[2] | r_ava_alw_rdy[3] | r_ava_alw_rdy[4] | r_ava_alw_rdy[5] | r_ava_alw_rdy[6]   :
                                (w_ava_allow == 4'h8)?  av_ready | r_ava_alw_rdy[0] | r_ava_alw_rdy[1] | r_ava_alw_rdy[2] | r_ava_alw_rdy[3] | r_ava_alw_rdy[4] | r_ava_alw_rdy[5] | r_ava_alw_rdy[6] | r_ava_alw_rdy[7]    :
                                1'b0    ;

//  input pipeline
    always @ (posedge vclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_conven_v1     <=  1'b0    ;
            r_conven_v2     <=  1'b0    ;
            r_vsync_b_1     <=  1'b1    ;
            r_vsync_b_2     <=  1'b1    ;
            r_hsync_b       <=  1'b1    ;
            r_en            <=  1'b0    ;
            r_data_in       <=  32'h00000000    ;
        end
        else begin
            r_conven_v1     <=  conv_en         ;
            r_conven_v2     <=  r_conven_v1     ;
            r_vsync_b_1     <=  vsync_b         ;
            r_vsync_b_2     <=  r_vsync_b_1     ;
            r_hsync_b       <=  hsync_b         ;
            r_en            <=  data_en         ;
            r_data_in       <=  {8'h00,vdata}   ;
        end
    end

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_conven_a1     <=  1'b0    ;
            r_conven_a2     <=  1'b0    ;
        end
        else begin
            r_conven_a1     <=  conv_en     ;
            r_conven_a2     <=  r_conven_a1 ;
        end
    end

//  state machine
    always @ (posedge vclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
        	r_vid_state     <=  p_vid_idle  ;
        end
        else begin
            case (r_vid_state) 
                p_vid_idle  :   begin
                    if(r_conven_v2  == 1'b1) begin
                    	r_vid_state <=  p_vid_wait  ;
                    end
                end
                p_vid_wait  :   begin
                    if(r_conven_v2 == 1'b0) begin
                    	r_vid_state <=  p_vid_idle  ;
                    end
                    else if((r_vsync_b_1 == 1'b0)&&(r_vsync_b_2 == 1'b1)) begin
                    	r_vid_state <=  p_vid_write ;
                    end
                end
                p_vid_write :   begin
                    if(r_conven_v2 == 1'b0) begin
                   		r_vid_state <=  p_vid_idle  ;
                    end
                end
                default     :   begin
                	r_vid_state     <=  p_vid_idle  ;
                end
            endcase
        end
    end

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_a_state   <=  p_a_idle    ;
        end
        else begin
            case(r_a_state)
                p_a_idle    :   begin
                    if(r_conven_a2  == 1'b1) begin
                        r_a_state   <=  p_a_wait    ;
                    end
                end
                p_a_wait    :   begin
                    if(r_conven_a2  == 1'b0) begin
                        r_a_state   <=  p_a_idle    ;
                    end
                    else begin
                        case(r_state_move)
                            p_to_ctr    :   begin
                                r_a_state   <=  p_a_ctr ;
                            end
                            p_to_rd     :   begin
                                r_a_state   <=  p_a_read    ;
                            end
                        endcase
                    end
                end
                p_a_ctr :   begin
                    if(r_conven_a2  == 1'b0) begin
                        r_a_state   <=  p_a_idle    ;
                    end
                    else if(r_ava_ctr_cnt == p_ctr_cnt_max) begin
                        r_a_state   <=  p_a_wait    ;
                    end
                end
                p_a_read    :   begin
                    if(r_conven_a2  == 1'b0) begin
                        r_a_state   <=  p_a_idle    ;
                    end

                    else if(r_a_vcnt == p_v_size)   begin
                        r_a_state   <=  p_a_wait    ;
                    end
                end
            endcase
        end
    end

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_state_move    <=  p_move_wait ;
        end
        else if(r_a_state == p_a_wait)  begin
            if(w_empty == 1'b0)begin
                if(st_sel == p_ax_mode) begin
                    r_state_move    <=  p_to_rd ;
                end
                else begin
                    r_state_move    <=  p_to_ctr    ;
                end
            end
            else begin
                r_state_move    <=  p_move_wait ;
            end
        end
        else if(r_a_state == p_a_ctr)   begin
            if(r_ava_ctr_cnt == p_ctr_cnt_max) begin
                r_state_move    <=  p_to_rd ;
            end
            else begin
                r_state_move    <=  p_move_wait ;
            end
        end
        else begin
            r_state_move    <=  p_move_wait ;
        end
    end

//  FIFO(data_width = 32    fifo_depth = 8192   show-ahead)
    assign w_aclr_b     =   aresetn & r_conven_v2 & r_conven_a2 ;
    assign w_aclr       =   ~w_aclr_b           ;
    assign w_empty_b    =   ~w_empty            ;
    assign w_ready      =   (st_sel == p_ax_mode)?      ax_tready   :   w_ava_alw_rdy   ;
    assign w_read_en    =   (r_a_hcnt == p_h_size)?	1'b0	:r_read_en & w_ready & w_empty_b         ;
    assign w_write_en   =   (r_vid_state == p_vid_write)?   r_en    :   1'b0            ;

    fifo_vid_av u1  (
        .aclr(w_aclr)       ,
        .data(r_data_in)    ,
        .rdclk(aclk)        ,
        .rdreq(w_read_en)   ,
        .wrclk(vclk)        ,
        .wrreq(w_write_en)  ,
        .q(w_data_out)      ,
        .rdempty(w_empty)   ,
        .wrfull(w_full)     
    );

    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_read_en   <=  1'b0    ;
        end
        else if(r_a_state == p_a_read)begin
            if(st_sel == p_ax_mode)begin
                if(r_state_move == p_to_rd)begin
                    r_read_en   <=  1'b1    ;
                end
                else if((r_a_hcnt == p_h_size)&&(r_a_vcnt == p_v_size1)&&(r_tval == 1'b1)&&(w_ready == 1'b1)) begin
                    r_read_en   <=  1'b0    ;
                end
            end
            else begin
                if((r_ava_valid == 1'b1)&&(r_ava_start == 1'b1)&&(w_ready == 1'b1))begin
                    r_read_en   <=  1'b1    ;
                end
                else if((r_ava_end == 1'b1)&&(r_ava_valid == 1'b1)&&(w_ready == 1'b1)) begin
                    r_read_en   <=  1'b0    ;
                end
            end
        end
        else begin
            r_read_en   <=  1'b0    ;
        end
    end

//	HVcounter
    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_a_hcnt <= 11'h000 ;
        end
        else if(r_read_en == 1'b1) begin
            if(r_a_hcnt == p_h_size) begin
				if(st_sel == p_ax_mode) begin
					if((r_tval == 1'b1)&&(w_ready == 1'b1))begin
	                	r_a_hcnt <= 11'd0   ;
					end
				end
				else begin
					if((r_ava_valid == 1'b1)&&(w_ready == 1'b1))begin
	                	r_a_hcnt <= 11'd0   ;
					end
				end
            end
            else if(w_read_en == 1'b1) begin
                r_a_hcnt <= r_a_hcnt + 11'd1    ;
            end
        end
        else begin
            r_a_hcnt <= 11'h000 ;
        end
    end

    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_a_vcnt <= 11'h000 ;
        end
        else if(r_read_en == 1'b1) begin
            if(st_sel == p_ax_mode)begin
                if((r_a_hcnt == p_h_size)&&(r_tval == 1'b1)&&(w_ready == 1'b1))begin
                    r_a_vcnt <= r_a_vcnt + 11'd1    ;
                end
            end
            else begin
                if((r_a_hcnt == p_h_size)&&(r_ava_valid == 1'b1)&&(w_ready == 1'b1))begin
                    r_a_vcnt <= r_a_vcnt + 11'd1    ;
                end
            end
        end
        else begin
            r_a_vcnt <= 11'h000 ;
        end
    end

//  AXI4-stream
    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_tval      <=  1'b0    ;
        end
        else if(r_a_state == p_a_read) begin
            if(w_read_en == 1'b1) begin
                r_tval      <=  1'b1    ;
            end
            else if(w_ready == 1'b1) begin
                r_tval      <=  1'b0    ;
            end
        end
        else begin
            r_tval      <=  1'b0    ;
        end
    end

    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_tuser     <=  1'b0    ;
        end
        else if(r_a_state == p_a_read) begin
            if((r_tuser == 1'b1)&&(r_tval == 1'b1)&&(w_ready == 1'b1)) begin
                r_tuser     <=  1'b0    ;
            end
            else if((r_a_hcnt == 11'd0)&&(r_a_vcnt == 11'd0)) begin
                r_tuser     <=  1'b1    ;
            end
        end
        else begin
            r_tuser     <=  1'b0    ;
        end
    end

    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_tlast     <=  1'b0    ;
        end
        else if(r_a_state == p_a_read) begin
            if((r_tlast == 1'b1)&&(r_tval == 1'b1)&&(w_ready == 1'b1)) begin
                r_tlast     <=  1'b0    ;
            end
            else if((r_a_hcnt == p_h_size1)&&(w_read_en == 1'b1)) begin
                r_tlast     <=  1'b1    ;
            end
        end
        else begin
            r_tlast     <=  1'b0    ;
        end
    end

    always @ (posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_tdata     <=  32'h00000000    ;
        end
        else if(r_a_state == p_a_read) begin
            if(w_read_en == 1'b1) begin
                r_tdata     <=  w_data_out      ;
            end
        end
        else begin
            r_tdata     <=  32'h00000000    ;
        end
    end

//  AvalonST
    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_ctr_cnt   <=  3'd0    ;
        end
        else if(r_a_state == p_a_ctr) begin
            if ((r_ava_valid == 1'b1)&&(w_ready == 1'b1)) begin
                r_ava_ctr_cnt   <=  r_ava_ctr_cnt + 3'd1    ;
            end
        end
        else begin
            r_ava_ctr_cnt   <=  3'd0    ;
        end
    end

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_start <=  1'b0    ;
        end
        else if((r_ava_start == 1'b1)&&(r_ava_valid == 1'b1)&&(w_ready == 1'b1)) begin
            r_ava_start <=  1'b0    ;
        end
        else if(r_a_state == p_a_ctr) begin
            if(r_ava_ctr_cnt == 3'd0) begin
                r_ava_start <=  1'b1    ;
            end
        end
        else if(r_a_state == p_a_read) begin
            if((r_a_vcnt == 11'd0)&&(r_read_en == 1'b0)) begin
                r_ava_start <=  1'b1    ;
            end
        end
        else begin
            r_ava_start <=  1'b0    ;
        end
    end

   always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_end   <=  1'b0    ;
        end
        else if((r_ava_end == 1'b1)&&(r_ava_valid == 1'b1)) begin
			if(w_ready == 1'b1) begin
            	r_ava_end <=    1'b0    ;
			end
        end
        else if(r_a_state == p_a_ctr)begin
			if((r_ava_ctr_cnt == p_ctr_cnt_max2)&&(w_ready == 1'b1)) begin
                r_ava_end   <=  1'b1    ;
            end
        end
        else if(r_a_state == p_a_read) begin
            if(	((r_a_vcnt == p_v_size1)&&(r_a_hcnt == p_h_size1)&&(w_read_en == 1'b1))||
				((r_a_hcnt == p_h_size)&&(r_ava_valid == 1'b1)&&(w_ready == 1'b1))	)	begin
                r_ava_end   <=  1'b1    ;
            end
			else begin
                r_ava_end   <=  1'b0    ;
            end
		end
        else begin
            r_ava_end   <=  1'b0    ;
        end
    end

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_valid <=  1'b0    ;
        end
        else if(r_a_state == p_a_ctr)begin
            if(r_ava_ctr_cnt == 3'd0) begin
                r_ava_valid <=  1'b1    ;
            end
            else if((r_ava_ctr_cnt == p_ctr_cnt_max1)&&(w_ready == 1'b1)) begin
                r_ava_valid <=  1'b0    ;
            end
        end
        else if(r_a_state == p_a_read) begin
            if(r_read_en == 1'b1) begin
                if((r_a_hcnt == p_h_size)&&(r_ava_valid == 1'b1)&&(w_ready == 1'b1)) begin
                    r_ava_valid     <=  1'b0    ;
                end
                else if(w_read_en == 1'b1) begin
                    r_ava_valid     <=  1'b1    ;
                end
                else if(w_ready == 1'b1) begin
                    r_ava_valid     <=  1'b0    ;
                end
            end
            else if((r_ava_valid == 1'b1)&&(r_ava_start == 1'b1)&&(w_ready == 1'b1))begin
                r_ava_valid     <=  1'b0    ;
            end
            else if(r_a_vcnt == p_v_size)begin
                r_ava_valid     <=  1'b0    ;
            end
            else begin
                r_ava_valid     <=  1'b1    ;
            end
        end
        else begin
            r_ava_valid     <=  1'b0    ;
        end
    end

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_data  <=  32'h00000000    ;
        end
        else if(r_a_state == p_a_wait) begin
            if(r_state_move == p_to_ctr)begin
                r_ava_data  <=  p_ctr_start ;
            end
            else if(r_state_move == p_to_rd)begin
                r_ava_data  <=  p_vid_start ;
            end
            else begin
                r_ava_data  <=  32'h00000000    ;
            end
        end
        else if(r_a_state == p_a_ctr) begin
            if((r_ava_valid == 1'b1)&&(w_ready == 1'b1))begin
                case(r_ava_ctr_cnt) 
                    3'd0    :   begin
                        r_ava_data[ 7: 0]   <=  {4'h0,p_h_size[ 3:0]}   ;
                        r_ava_data[15: 8]   <=  {4'h0,p_h_size[ 7:4]}   ;
                        r_ava_data[23:16]   <=  {4'h0,p_h_size[11:8]}   ;
                        r_ava_data[31:24]   <=  8'h0                    ;
                    end
                    3'd1    :   begin
                        r_ava_data[ 7: 0]   <=  {4'h0,p_v_size[ 3:0]}   ;
                        r_ava_data[15: 8]   <=  {4'h0,p_v_size[ 7:4]}   ;
                        r_ava_data[23:16]   <=  {4'h0,p_v_size[11:8]}   ;
                        r_ava_data[31:24]   <=  8'h0                    ;
                    end
                    p_ctr_cnt_max2  :   begin
                        r_ava_data          <=  p_ctr_interlace          ;
                    end
                    default :   begin
                        r_ava_data          <=  32'h00000000            ;
                    end
                endcase
            end
        end
        else if(r_a_state == p_a_read) begin
            if(w_read_en == 1'b1)begin
                r_ava_data  <=  w_data_out  ;
            end
        end
        else begin
            r_ava_data  <=  32'h00000000    ;
        end

    end

//  AvalonST latency
    assign  w_ava_late  =   p_ava_latency   ;

    always@(posedge aclk or negedge aresetn) begin
        if(aresetn == 1'b0) begin
            r_ava_late_val      <=  8'h00           ;
            r_ava_late_start    <=  8'h00           ;
            r_ava_late_end      <=  8'h00           ;
            r_ava_data1         <=  32'h00000000    ;
            r_ava_data2         <=  32'h00000000    ;
            r_ava_data3         <=  32'h00000000    ;
            r_ava_data4         <=  32'h00000000    ;
            r_ava_data5         <=  32'h00000000    ;
            r_ava_data6         <=  32'h00000000    ;
            r_ava_data7         <=  32'h00000000    ;
            r_ava_data8         <=  32'h00000000    ;
        end
        else begin
            r_ava_late_val      <=  {r_ava_late_val[6:0],r_ava_valid}       ;
            r_ava_late_start    <=  {r_ava_late_start[6:0],r_ava_start} ;
            r_ava_late_end      <=  {r_ava_late_end[6:0],r_ava_end}     ;
            r_ava_data1         <=  r_ava_data      ;
            r_ava_data2         <=  r_ava_data1     ;
            r_ava_data3         <=  r_ava_data2     ;
            r_ava_data4         <=  r_ava_data3     ;
            r_ava_data5         <=  r_ava_data4     ;
            r_ava_data6         <=  r_ava_data5     ;
            r_ava_data7         <=  r_ava_data6     ;
            r_ava_data8         <=  r_ava_data7     ;
        end
    end

    assign  w_ava_valid_o   =   (w_ava_late == 4'h0)?   r_ava_valid         :
                                (w_ava_late == 4'h1)?   r_ava_late_val[0]   :
                                (w_ava_late == 4'h2)?   r_ava_late_val[1]   :
                                (w_ava_late == 4'h3)?   r_ava_late_val[2]   :
                                (w_ava_late == 4'h4)?   r_ava_late_val[3]   :
                                (w_ava_late == 4'h5)?   r_ava_late_val[4]   :
                                (w_ava_late == 4'h6)?   r_ava_late_val[5]   :
                                (w_ava_late == 4'h7)?   r_ava_late_val[6]   :
                                (w_ava_late == 4'h8)?   r_ava_late_val[7]   :
                                                        1'b0                ;

    assign  w_ava_start_o   =   (w_ava_late == 4'h0)?   r_ava_start         :
                                (w_ava_late == 4'h1)?   r_ava_late_start[0] :
                                (w_ava_late == 4'h2)?   r_ava_late_start[1] :
                                (w_ava_late == 4'h3)?   r_ava_late_start[2] :
                                (w_ava_late == 4'h4)?   r_ava_late_start[3] :
                                (w_ava_late == 4'h5)?   r_ava_late_start[4] :
                                (w_ava_late == 4'h6)?   r_ava_late_start[5] :
                                (w_ava_late == 4'h7)?   r_ava_late_start[6] :
                                (w_ava_late == 4'h8)?   r_ava_late_start[7] :
                                                        1'b0                ;

    assign  w_ava_end_o     =   (w_ava_late == 4'h0)?   r_ava_end           :
                                (w_ava_late == 4'h1)?   r_ava_late_end[0]   :
                                (w_ava_late == 4'h2)?   r_ava_late_end[1]   :
                                (w_ava_late == 4'h3)?   r_ava_late_end[2]   :
                                (w_ava_late == 4'h4)?   r_ava_late_end[3]   :
                                (w_ava_late == 4'h5)?   r_ava_late_end[4]   :
                                (w_ava_late == 4'h6)?   r_ava_late_end[5]   :
                                (w_ava_late == 4'h7)?   r_ava_late_end[6]   :
                                (w_ava_late == 4'h8)?   r_ava_late_end[7]   :
                                                        1'b0                ;

    assign  w_ava_data_o    =   (w_ava_late == 4'h0)?   r_ava_data  :
                                (w_ava_late == 4'h1)?   r_ava_data1 :
                                (w_ava_late == 4'h2)?   r_ava_data2 :
                                (w_ava_late == 4'h3)?   r_ava_data3 :
                                (w_ava_late == 4'h4)?   r_ava_data4 :
                                (w_ava_late == 4'h5)?   r_ava_data5 :
                                (w_ava_late == 4'h6)?   r_ava_data6 :
                                (w_ava_late == 4'h7)?   r_ava_data7 :
                                (w_ava_late == 4'h8)?   r_ava_data8 :
                                                        32'h00000000;
//  output
    assign  ax_tdata    =   r_tdata     ;
    assign  ax_tvalid   =   r_tval      ;
    assign  ax_tuser    =   r_tuser     ;
    assign  ax_tlast    =   r_tlast     ;

    assign  av_data     =   w_ava_data_o    ;
    assign  av_valid    =   w_ava_valid_o   ;
    assign  av_start    =   w_ava_start_o   ;
    assign  av_end      =   w_ava_end_o ;
endmodule
```

# まとめと今後の課題
　今回は簡易な実装例ということで画像サイズはFullHD限定とし、パラメータはソースに埋め込んでいますが、実用的にはレジスタ設定で変更できる形にする必要があると思います。
　また、本回路とペアになる逆変換(ストリームデータから同期ビデオ信号)も必要と思いますので、機会を見て作成し投稿したいと考えています。