e-tipsmemo

ごった煮

Verilog ビデオ信号出力(Transition Minimized Differential Signaling)

いわゆるHDMIのV1.0でDVI-Dと互換のデータ形式

e-tipsmemo.hatenablog.com
の続き。
といっても
e-tipsmemo.hatenablog.com
Verilogにするだけ

module encoding(
    input clk,
    input resetn,
    input [7:0] din,
    output [9:0] dout,
    input disp_area,
    input c0,
    input c1
    );
    
    function [3:0] ones(input [7:0] in);
        begin
            ones = {3'b0,in[7]}+{3'b0,in[6]}+{3'b0,in[5]}+{3'b0,in[4]}+{3'b0,in[3]}+{3'b0,in[2]}+{3'b0,in[1]}+{3'b0,in[0]};   
        end
    endfunction
    
    function [3:0] zeros(input [7:0] in);
        begin
            zeros = 4'd8 - {3'b0,in[7]}+{3'b0,in[6]}+{3'b0,in[5]}+{3'b0,in[4]}+{3'b0,in[3]}+{3'b0,in[2]}+{3'b0,in[1]}+{3'b0,in[0]};   
        end
    endfunction
    
    function [9:0] xor_out(input [7:0] in);
        begin
            xor_out[0] = in[0];
            xor_out[1] = in[1]^xor_out[0];
            xor_out[2] = in[2]^xor_out[1];
            xor_out[3] = in[3]^xor_out[2];
            xor_out[4] = in[4]^xor_out[3];
            xor_out[5] = in[5]^xor_out[4];
            xor_out[6] = in[6]^xor_out[5];
            xor_out[7] = in[7]^xor_out[6];
            xor_out[8] = 1;
            xor_out[9] = 0;           
        end
    endfunction
    
    function [9:0] xnor_out(input [7:0] in);
        begin
            xnor_out[0] = in[0];
            xnor_out[1] = ~(in[1]^xnor_out[0]);
            xnor_out[2] = ~(in[2]^xnor_out[1]);
            xnor_out[3] = ~(in[3]^xnor_out[2]);
            xnor_out[4] = ~(in[4]^xnor_out[3]);
            xnor_out[5] = ~(in[5]^xnor_out[4]);
            xnor_out[6] = ~(in[6]^xnor_out[5]);
            xnor_out[7] = ~(in[7]^xnor_out[6]);
            xnor_out[8] = 0;
            xnor_out[9] = 0;           
        end
    endfunction
    
    reg[9:0] d00 = 10'b1101010100;
    reg[9:0] d01 = 10'b0010101011;
    reg[9:0] d10 = 10'b0101010100;
    reg[9:0] d11 = 10'b1010101011;
    
    wire clk;
    wire resetn;
    wire[7:0] din;
    
    reg[9:0] dout;
    reg[9:0] dout1;
    wire disp_area;
    wire c0;
    wire c1;
    reg c0_d;
    reg c1_d;
    reg disp_d;
    reg disp_dd;
    
    wire[3:0] dones;
    assign dones = ones(din);
    
    always@(posedge clk)begin
        if(resetn == 1'b0)begin
            disp_d <= 1'b0;
            dout1 <= 10'b0;
            c0_d <= 1'b0;
            c1_d <= 1'b0;
        end
        else begin
            disp_d <= disp_area;

            
            if(disp_area == 1'b1)begin
                if((dones >= 4'd5)||((dones == 4'd4)&&(din[0] == 1'b0)))begin
                    dout1 <= xnor_out(din);
                end 
                else begin
                    dout1 <= xor_out(din);
                end
            end
            else begin
                dout1 <= 10'b0;
                c0_d <= c0;
                c1_d <= c1;
            end 
        
    
        end
    end
    
    reg signed [4:0] cnt;
    wire[3:0] n1;
    wire[3:0] n0;
    
    assign n1 = ones(dout1[7:0]);
    assign n0 = 4'd8 - n1;
        
    always@(posedge clk)begin
        if(resetn == 1'b0)begin
             disp_dd <= 1'b0;;
             dout <= 10'b0;
        end
        else begin
             disp_dd <= disp_d;
             if(disp_dd == 1'b0 && disp_d == 1'b1)begin
                cnt <= 0;
             end
             
             if(disp_d == 1'b1) begin
                 if(disp_d == 1'b1)begin
                    if((cnt == 5'b0)||(n1 == 4'd4))begin
                        dout[9] <= ~dout1[8];
                        dout[8] <= dout1[8];
                        if(dout1[8] == 1'b0)begin
                            dout[7:0] <= ~dout1[7:0];
                            cnt <= cnt + n0 - n1;
                        end
                        else begin
                            dout[7:0] <= dout1[7:0];
                            cnt <= cnt + n1 - n0;
                        end
                    end 
                    else begin
                        if(((cnt > 0)&&(n1 > 4))||((cnt < 0)&&(n1 < 4)))begin
                            dout[9] <= 1'b1;
                            dout[8] <= dout1[8];
                            dout[7:0] <= ~dout1[7:0];
                            
                            if(dout1[8] == 1'b0)begin
                               cnt <= cnt + n0 - n1; 
                            end
                            else begin
                                cnt <= cnt + n0 - n1 + 2;
                            end
                        end
                        else begin
                            dout[9] <= 1'b0;
                            dout[8:0] <= dout1[8:0];
                            
                            if(dout1[8] == 1'b0)begin
                                cnt <= cnt + (n1 - n0) - 2;
                            end
                            else begin
                                cnt <= cnt + n1 - n0;
                            end
                        end
                    end
                 end
             end
             else begin
                case({c1_d,c0_d})
                    2'b00 : begin
                                dout <= d00;
                            end 
                    2'b01 : begin
                                dout <= d01;
                            end 
                    2'b10 : begin
                                dout <= d10;
                            end 
                    2'b11 : begin
                                dout <= d11;
                            end 
                endcase
             end
        end
    end
    
endmodule


V1.2?以上に必要となるガードバンドなどはここでタイミングを制御するべきであろうか