dakies/OSS_Verilog huggingface dataset:
module jelly_gpio
        #(
            parameter   WB_ADR_WIDTH   = 2,
            parameter   WB_DAT_WIDTH   = 32,
            parameter   WB_SEL_WIDTH   = (WB_DAT_WIDTH / 8),
            parameter   PORT_WIDTH     = 8,
            parameter   INIT_DIRECTION = 0,
            parameter   INIT_OUTPUT    = 0,
            parameter   DIRECTION_MASK = 0
        )
        (
            // system
            input   wire                        reset,
            input   wire                        clk,
            
            // port
            input   wire    [PORT_WIDTH-1:0]    port_i,
            output  wire    [PORT_WIDTH-1:0]    port_o,
            output  wire    [PORT_WIDTH-1:0]    port_t,
            
            // control port (wishbone)
            input   wire    [WB_ADR_WIDTH-1:0]  s_wb_adr_i,
            output  reg     [WB_DAT_WIDTH-1:0]  s_wb_dat_o,
            input   wire    [WB_DAT_WIDTH-1:0]  s_wb_dat_i,
            input   wire                        s_wb_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]  s_wb_sel_i,
            input   wire                        s_wb_stb_i,
            output  wire                        s_wb_ack_o
        );
    
    // register address
    localparam  GPIO_ADR_DIRECTION = 2'b00;
    localparam  GPIO_ADR_INPUT     = 2'b01;
    localparam  GPIO_ADR_OUTPUT    = 2'b10;
    
    
    // control
    reg     [PORT_WIDTH-1:0]    reg_direction;
    reg     [PORT_WIDTH-1:0]    reg_output;
    
    always @ ( posedge clk ) begin
        if ( reset ) begin
            reg_direction <= INIT_DIRECTION;
            reg_output    <= INIT_OUTPUT;
        end
        else begin
            // direction
            if ( s_wb_stb_i & s_wb_we_i & (s_wb_adr_i == GPIO_ADR_DIRECTION) ) begin
                reg_direction <= ((reg_direction & DIRECTION_MASK) | (s_wb_dat_i[PORT_WIDTH-1:0] & ~DIRECTION_MASK));
            end
            
            // output
            if ( s_wb_stb_i & s_wb_we_i & (s_wb_adr_i == GPIO_ADR_OUTPUT) ) begin
                reg_output <= s_wb_dat_i[PORT_WIDTH-1:0];
            end
        end
    end
    
    assign port_o = reg_output;
    assign port_t = ~reg_direction;
    
    always @* begin
        case ( s_wb_adr_i )
        GPIO_ADR_DIRECTION: begin   s_wb_dat_o <= reg_direction;            end
        GPIO_ADR_INPUT:     begin   s_wb_dat_o <= port_i;                   end
        GPIO_ADR_OUTPUT:    begin   s_wb_dat_o <= reg_output;               end
        default:            begin   s_wb_dat_o <= {WB_DAT_WIDTH{1'b0}};     end
        endcase
    end
    
    assign s_wb_ack_o = s_wb_stb_i;
    
endmodule
module jelly_video_rgb_to_gray
        #(
            parameter   COMPONENT_NUM = 3,
            parameter   DATA_WIDTH    = 8,
            
            parameter   TUSER_WIDTH   = 1,
            parameter   TDATA_WIDTH   = COMPONENT_NUM*DATA_WIDTH
        )
        (
            input   wire                        aresetn,
            input   wire                        aclk,
            
            input   wire    [TUSER_WIDTH-1:0]   s_axi4s_tuser,
            input   wire                        s_axi4s_tlast,
            input   wire    [TDATA_WIDTH-1:0]   s_axi4s_tdata,
            input   wire                        s_axi4s_tvalid,
            output  wire                        s_axi4s_tready,
            
            output  wire    [TUSER_WIDTH-1:0]   m_axi4s_tuser,
            output  wire                        m_axi4s_tlast,
            output  wire    [TDATA_WIDTH-1:0]   m_axi4s_tdata,
            output  wire    [DATA_WIDTH-1:0]    m_axi4s_tgray,
            output  wire                        m_axi4s_tvalid,
            input   wire                        m_axi4s_tready
        );
    
    wire                            cke;
    
    reg     [TUSER_WIDTH-1:0]       st0_tuser;
    reg                             st0_tlast;
    reg     [TDATA_WIDTH-1:0]       st0_tdata;
    reg     [DATA_WIDTH-1:0]        st0_tgray;
    reg                             st0_tvalid;
    
    always @(posedge aclk) begin
        if ( ~aresetn ) begin
            st0_tuser  <= {TUSER_WIDTH{1'bx}};
            st0_tlast  <= 1'bx;
            st0_tdata  <= {TDATA_WIDTH{1'bx}};
            st0_tgray  <= {DATA_WIDTH{1'bx}};
            st0_tvalid <= 1'b0;
        end
        else if ( cke ) begin
            st0_tuser  <= s_axi4s_tuser;
            st0_tlast  <= s_axi4s_tlast;
            st0_tdata  <= s_axi4s_tdata;
            st0_tgray  <= (({2'b00, s_axi4s_tdata[2*DATA_WIDTH +: DATA_WIDTH]}
                            + {1'b0, s_axi4s_tdata[1*DATA_WIDTH +: DATA_WIDTH], 1'b0}
                            + {2'b00, s_axi4s_tdata[0*DATA_WIDTH +: DATA_WIDTH]}) >> 2);
            st0_tvalid <= s_axi4s_tvalid;
        end
    end
    
    assign cke = !m_axi4s_tvalid || m_axi4s_tready;
    
    assign s_axi4s_tready = cke;
    
    assign m_axi4s_tuser   = st0_tuser;
    assign m_axi4s_tlast   = st0_tlast;
    assign m_axi4s_tgray   = st0_tgray;
    assign m_axi4s_tdata   = st0_tdata;
    assign m_axi4s_tvalid  = st0_tvalid;
    
endmodule
module jelly_dvi_rx_decode
        (
            input   wire            reset,
            input   wire            clk,
            
            input   wire    [9:0]   in_d,
            
            output  wire            out_de,
            output  wire    [7:0]   out_d,
            output  wire            out_c0,
            output  wire            out_c1
        );
    
    // stage 0
    wire    [9:0]       st0_d = in_d;
    
    // stage 1
    reg                 st1_de;
    reg                 st1_c0;
    reg                 st1_c1;
    reg     [7:0]       st1_d;
    
    always @(posedge clk) begin
        if ( reset ) begin
            st1_de    <= 1'b0;
            st1_c0    <= 1'b0;
            st1_c1    <= 1'b0;
            st1_d     <= {8{1'bx}};
        end
        else begin
            // stage 1
            st1_de <= 1'b0;
            case ( st0_d )
            10'b1101010100: {st1_c1, st1_c0} <= 2'b00;
            10'b0010101011: {st1_c1, st1_c0} <= 2'b01;
            10'b0101010100: {st1_c1, st1_c0} <= 2'b10;
            10'b1010101011: {st1_c1, st1_c0} <= 2'b11;
            default:
                begin
                st1_de <= 1'b1;
                case ( st0_d[9:8] )
                2'b00 : st1_d <= ~( st0_d[7:0] ^ { st0_d[6:1], 1'b1});
                2'b01 : st1_d <=  ( st0_d[7:0] ^ { st0_d[6:1], 1'b0});
                2'b10 : st1_d <= ~(~st0_d[7:0] ^ {~st0_d[6:1], 1'b1});
                2'b11 : st1_d <=  (~st0_d[7:0] ^ {~st0_d[6:1], 1'b0});
                endcase
                end
            endcase
        end
    end
    
    assign out_de = st1_de;
    assign out_d  = st1_d;
    assign out_c0 = st1_c0;
    assign out_c1 = st1_c1;
    
endmodule
module jelly_mipi_rx_lane_recv
        #(
            parameter   LANES = 2
        )
        (
            input   wire                    reset,
            input   wire                    clk,
            
            // input
            input   wire    [LANES*8-1:0]   in_rxdatahs,       // data
            input   wire    [LANES-1:0]     in_rxvalidhs,      // syncコードでは立たない
            input   wire    [LANES-1:0]     in_rxactivehs,     // hs期間
            input   wire    [LANES-1:0]     in_rxsynchs,       // syncコード
            
            // output
            output  wire                    out_first,
            output  wire                    out_last,
            output  wire    [LANES*8-1:0]   out_data,
            output  wire                    out_valid
        );
    
    reg     [LANES*8-1:0]   st0_rxdatahs;
    reg     [LANES-1:0]     st0_rxvalidhs;
    reg     [LANES-1:0]     st0_rxactivehs;
    reg     [LANES-1:0]     st0_rxsynchs;
    
    reg                     st1_busy;
    reg     [LANES*8-1:0]   st1_data;
    reg                     st1_first;
    reg                     st1_last;
    reg                     st1_valid;
    
    always @(posedge clk) begin
        if ( reset ) begin
            st0_rxdatahs   <= {LANES{8'hxx}};
            st0_rxvalidhs  <= {LANES{1'b0}};
            st0_rxactivehs <= {LANES{1'b0}};
            st0_rxsynchs   <= {LANES{1'b0}};
            
            st1_busy       <= 1'b0;
            st1_data       <= {LANES{8'hxx}};
            st1_first      <= 1'bx;
            st1_last       <= 1'bx;
            st1_valid      <= 1'b0;
        end
        else begin
            // stage 0
            st0_rxdatahs   <= in_rxdatahs;
            st0_rxvalidhs  <= in_rxvalidhs;
            st0_rxactivehs <= in_rxactivehs;
            st0_rxsynchs   <= in_rxsynchs;
            
            
            // stage 1
            if ( &st0_rxsynchs & &in_rxactivehs ) begin
                st1_busy <= 1'b1;
            end
            else if ( st1_valid & st1_last ) begin
                st1_busy <= 1'b0;
            end
            
            if ( &st0_rxsynchs & &in_rxactivehs ) begin
                st1_first <= 1'b1;
            end
            else if ( st1_valid ) begin
                st1_first <= 1'b0;
            end
            
            st1_last  <= ((in_rxactivehs == 0) || (in_rxvalidhs == 0) | (in_rxsynchs != 0));
            st1_data  <= st0_rxdatahs;
            st1_valid <= ((st0_rxvalidhs != 0) && st1_busy);
        end
    end
    
    assign out_first = st1_first;
    assign out_last  = st1_last;
    assign out_data  = st1_data;
    assign out_valid = st1_valid;
    
endmodule
module jelly_serdes_10to1_7series
        (
            input   wire            reset,
            input   wire            clk,
            input   wire            clk_x5,
            
            input   wire    [9:0]   in_data,
            
            output  wire            out_data
        );

`ifndef SIMULATION

    wire            shift1;
    wire            shift2;
    
    OSERDESE2
            #(
                .DATA_RATE_OQ   ("DDR"),
                .DATA_RATE_TQ   ("SDR"),
                .DATA_WIDTH     (10),
                .TRISTATE_WIDTH (1),
                .SERDES_MODE    ("MASTER")
            )
        i_oserdese2_master
            (
                .D1             (in_data[0]),
                .D2             (in_data[1]),
                .D3             (in_data[2]),
                .D4             (in_data[3]),
                .D5             (in_data[4]),
                .D6             (in_data[5]),
                .D7             (in_data[6]),
                .D8             (in_data[7]),
                .T1             (1'b0),
                .T2             (1'b0),
                .T3             (1'b0),
                .T4             (1'b0),
                .SHIFTIN1       (shift1),
                .SHIFTIN2       (shift2),
                .SHIFTOUT1      (),
                .SHIFTOUT2      (),
                .OCE            (1'b1),
                .CLK            (clk_x5),
                .CLKDIV         (clk),
                .OQ             (out_data),
                .TQ             (),
                .OFB            (),
                .TFB            (),
                .TBYTEIN        (1'b0),
                .TBYTEOUT       (),
                .TCE            (1'b0),
                .RST            (reset)
                );
    
    OSERDESE2
            #(
                .DATA_RATE_OQ   ("DDR"),
                .DATA_RATE_TQ   ("SDR"),
                .DATA_WIDTH     (10),
                .TRISTATE_WIDTH (1),
                .SERDES_MODE    ("SLAVE")
            )
       i_oserdese2_slave
            (
                .D1             (1'b0), 
                .D2             (1'b0),
                .D3             (in_data[8]),
                .D4             (in_data[9]),
                .D5             (1'b0),
                .D6             (1'b0),
                .D7             (1'b0),
                .D8             (1'b0),
                .T1             (1'b0),
                .T2             (1'b0),
                .T3             (1'b0),
                .T4             (1'b0),
                .SHIFTOUT1      (shift1),
                .SHIFTOUT2      (shift2),
                .SHIFTIN1       (1'b0),
                .SHIFTIN2       (1'b0),
                .OCE            (1'b1),
                .CLK            (clk_x5),
                .CLKDIV         (clk),
                .OQ             (),
                .TQ             (),
                .OFB            (),
                .TFB            (),
                .TBYTEIN        (1'b0),
                .TBYTEOUT       (),
                .TCE            (1'b0),
                .RST            (reset)
            );

`endif

endmodule
module jelly_video_binarizer_core
        #(
            parameter   TUSER_WIDTH = 1,
            parameter   TDATA_WIDTH = 8
        )
        (
            input   wire                        aresetn,
            input   wire                        aclk,
            
            input   wire    [TDATA_WIDTH-1:0]   param_th,
            input   wire                        param_inv,
            
            input   wire    [TUSER_WIDTH-1:0]   s_axi4s_tuser,
            input   wire                        s_axi4s_tlast,
            input   wire    [TDATA_WIDTH-1:0]   s_axi4s_tdata,
            input   wire                        s_axi4s_tvalid,
            output  wire                        s_axi4s_tready,
            
            output  wire    [TUSER_WIDTH-1:0]   m_axi4s_tuser,
            output  wire                        m_axi4s_tlast,
            output  wire    [0:0]               m_axi4s_tbinary,
            output  wire    [TDATA_WIDTH-1:0]   m_axi4s_tdata,
            output  wire                        m_axi4s_tvalid,
            input   wire                        m_axi4s_tready
        );
    
    wire                            cke;
    
    reg     [TUSER_WIDTH-1:0]       st0_tuser;
    reg                             st0_tlast;
    reg     [0:0]                   st0_tbinary;
    reg     [TDATA_WIDTH-1:0]       st0_tdata;
    reg                             st0_tvalid;
    
    always @(posedge aclk) begin
        if ( ~aresetn ) begin
            st0_tuser       <= {TUSER_WIDTH{1'bx}};
            st0_tlast       <= 1'bx;
            st0_tdata       <= {TDATA_WIDTH{1'bx}};
            st0_tbinary     <= 1'bx;
            st0_tvalid      <= 1'b0;
        end
        else if ( cke ) begin
            st0_tuser   <= s_axi4s_tuser;
            st0_tlast   <= s_axi4s_tlast;
            st0_tdata   <= s_axi4s_tdata;
            st0_tvalid  <= s_axi4s_tvalid;
            if ( s_axi4s_tdata > param_th ) begin
                st0_tbinary <= 1'b1 ^ param_inv;
            end
            else begin
                st0_tbinary <= 1'b0 ^ param_inv;
            end
        end
    end
    
    assign cke = !m_axi4s_tvalid || m_axi4s_tready;
    
    assign s_axi4s_tready = cke;
    
    assign m_axi4s_tuser   = st0_tuser;
    assign m_axi4s_tlast   = st0_tlast;
    assign m_axi4s_tbinary = st0_tbinary;
    assign m_axi4s_tdata   = st0_tdata;
    assign m_axi4s_tvalid  = st0_tvalid;
    
endmodule
module jelly_vin_axi4s
        #(
            parameter   WIDTH = 24
        )
        (
            input   wire                reset,
            input   wire                clk,
            
            // input timing
            input   wire                in_vsync,
            input   wire                in_hsync,
            input   wire                in_de,
            input   wire    [WIDTH-1:0] in_data,
            input   wire    [3:0]       in_ctl,
            
            // slave AXI4-Stream (input)
            output  wire    [0:0]       m_axi4s_tuser,
            output  wire                m_axi4s_tlast,
            output  wire    [WIDTH-1:0] m_axi4s_tdata,
            output  wire                m_axi4s_tvalid
        );
    
    reg                 st0_vsync;
    reg                 st0_de;
    reg     [WIDTH-1:0] st0_data;
    
    reg                 st1_tuser;
    reg                 st1_tlast;
    reg     [WIDTH-1:0] st1_tdata;
    reg                 st1_tvalid;
    
    always @(posedge clk) begin
        if ( reset ) begin
            st0_vsync  <= in_vsync;
            st0_de     <= 1'b0;
            st0_data   <= {WIDTH{1'bx}};
            
            st1_tuser  <= 1'bx;
            st1_tlast  <= 1'bx;
            st1_tdata  <= {WIDTH{1'bx}};
            st1_tvalid <= 1'b0;
        end
        else begin
            st0_vsync  <= in_vsync;
            st0_de     <= in_de;
            st0_data   <= in_data;
            
            // frame start
            if ( st0_vsync != in_vsync ) begin
                st1_tuser <= 1'b1;
            end
            else if ( st1_tvalid ) begin
                st1_tuser <= 1'b0;
            end
            
            st1_tlast  <= (st0_de && !in_de);
            st1_tdata  <= st0_data;
            st1_tvalid <= st0_de;
        end
    end
    
    assign m_axi4s_tuser  = st1_tuser;
    assign m_axi4s_tlast  = st1_tlast;
    assign m_axi4s_tdata  = st1_tdata;
    assign m_axi4s_tvalid = st1_tvalid;
    
endmodule
module jelly_multiplexer16
        #(
            parameter   DEVICE = "RTL"
        )
        (
            output  wire            o,
            input   wire    [15:0]  i,
            input   wire    [3:0]   s
        );
    
    generate
    if ( DEVICE == "VIRTEX6" || DEVICE == "SPARTAN6" || DEVICE == "7SERIES" ) begin : blk_lut6
        
        wire    [3:0]   l;
        
        LUT6
                #(
                    .INIT(64'hFF00F0F0CCCCAAAA)
                )
            i_lut6_0
                (
                    .O      (l[0]),
                    
                    .I0     (i[0]),
                    .I1     (i[1]),
                    .I2     (i[2]),
                    .I3     (i[3]),
                    
                    .I4     (s[0]),
                    .I5     (s[1])
                );
        
        LUT6
                #(
                    .INIT(64'hFF00F0F0CCCCAAAA)
                )
            i_lut6_1
                (
                    .O      (l[1]),
                    
                    .I0     (i[4]),
                    .I1     (i[5]),
                    .I2     (i[6]),
                    .I3     (i[7]),
                    
                    .I4     (s[0]),
                    .I5     (s[1])
                );
        
        LUT6
                #(
                    .INIT(64'hFF00F0F0CCCCAAAA)
                )
            i_lut6_2
                (
                    .O      (l[2]),
                    
                    .I0     (i[8]),
                    .I1     (i[9]),
                    .I2     (i[10]),
                    .I3     (i[11]),
                    
                    .I4     (s[0]),
                    .I5     (s[1])
                );
        
        LUT6
                #(
                    .INIT(64'hFF00F0F0CCCCAAAA)
                )
            i_lut6_3
                (
                    .O      (l[3]),
                    
                    .I0     (i[12]),
                    .I1     (i[13]),
                    .I2     (i[14]),
                    .I3     (i[15]),
                    
                    .I4     (s[0]),
                    .I5     (s[1])
                );
        
        
        wire    [1:0]   m;
        
        MUXF7
            i_mux7_0
                (
                    .O      (m[0]),
                    
                    .I0     (l[0]),
                    .I1     (l[1]),
                    
                    .S      (s[2])
                );
        
        MUXF7
            i_mux7_1
                (
                    .O      (m[1]),
                    
                    .I0     (l[2]),
                    .I1     (l[3]),
                    
                    .S      (s[2])
                );
        
        
        MUXF8
            i_mux8
                (
                    .O      (o),
                    
                    .I0     (m[0]),
                    .I1     (m[1]),
                    
                    .S      (s[3])
                );
        
    end
    else  begin : blk_rtl
        assign o = i[s];
    end
    endgenerate
    
    
endmodule
module jelly_ram64x1d_w1r2
        #(
            parameter   WIDTH  = 32,
            parameter   DEVICE = "RTL"
        )
        (
            input   wire                clk,
            
            input   wire                wr_en,
            input   wire    [5:0]       wr_addr,
            input   wire    [WIDTH-1:0] wr_data,
            
            input   wire    [5:0]       rd0_addr,
            output  wire    [WIDTH-1:0] rd0_data,
            
            input   wire    [5:0]       rd1_addr,
            output  wire    [WIDTH-1:0] rd1_data
        );
    
    genvar      i;
    
    generate
    for ( i = 0; i < WIDTH; i = i+1 ) begin : loop_ram64
        jelly_ram64x1d
                #(
                    .INIT       (64'h0000000000000000),
                    .DEVICE     (DEVICE)
                )
            i_ram64x1d_0
                (
                    .dpo        (rd0_data[i]),
                    .spo        (),
                    .a          (wr_addr),
                    .d          (wr_data[i]),
                    .dpra       (rd0_addr),
                    .wclk       (clk),
                    .we         (wr_en)
                );
        
        jelly_ram64x1d
                #(
                    .INIT       (64'h0000000000000000),
                    .DEVICE     (DEVICE)
                )
            i_ram64x1d_1
                (
                    .dpo        (rd1_data[i]),
                    .spo        (),
                    .a          (wr_addr),
                    .d          (wr_data[i]),
                    .dpra       (rd1_addr),
                    .wclk       (clk),
                    .we         (wr_en)
                );
    end
    endgenerate
    
    
endmodule
module jelly_ram64x1d
        #(
            parameter   INIT   = 64'h0000000000000000,
            parameter   DEVICE = "RTL" // "7SERIES"
        )
        (
            output  wire                dpo,
            output  wire                spo,
            input   wire    [5:0]       a,
            input   wire                d,
            input   wire    [5:0]       dpra,
            input   wire                wclk,
            input   wire                we
            
        );
    
    generate
    if ( DEVICE == "VIRTEX6" || DEVICE == "SPARTAN6" || DEVICE == "7SERIES" ) begin : blk_ram64x1d
        RAM64X1D
                #(
                    .INIT(INIT)
                )
            i_ram64x1d
                (
                    .DPO        (dpo),
                    .SPO        (spo),
                    .A0         (a[0]),
                    .A1         (a[1]),
                    .A2         (a[2]),
                    .A3         (a[3]),
                    .A4         (a[4]),
                    .A5         (a[5]),
                    .D          (d),
                    .DPRA0      (dpra[0]),
                    .DPRA1      (dpra[1]),
                    .DPRA2      (dpra[2]),
                    .DPRA3      (dpra[3]),
                    .DPRA4      (dpra[4]),
                    .DPRA5      (dpra[5]),
                    .WCLK       (wclk),
                    .WE         (we)
                );
    end
    else  begin : blk_rtl
        (* ram_style = "distributed" *)
        reg     [0:0]   mem     [0:63];
        
        always @(posedge wclk) begin
            if ( we ) begin
                mem[a] <= d;
            end
        end
        
        assign spo = mem[a];
        assign dpo = mem[dpra];
    end
    endgenerate
    
endmodule
module jelly_multiplexer4
        #(
            parameter   DEVICE = "RTL"
        )
        (
            output  wire            o,
            input   wire    [3:0]   i,
            input   wire    [1:0]   s
        );
    
    generate
    if ( DEVICE == "VIRTEX6" || DEVICE == "SPARTAN6" || DEVICE == "7SERIES" ) begin : blk_lut6
        LUT6
                #(
                    .INIT(64'hFF00F0F0CCCCAAAA)
                )
            i_lut6
                (
                    .O      (o),
                    .I0     (i[0]),
                    .I1     (i[1]),
                    .I2     (i[2]),
                    .I3     (i[3]),
                    .I4     (s[0]),
                    .I5     (s[1])
                );
    end
    else  begin : blk_rtl
        assign o = i[s];
    end
    endgenerate
    
    
endmodule
module jelly_rasterizer_plane_calc
        #(
            parameter   WIDTH = 16
        )
        (
            input   wire                            reset,
            input   wire                            clk,
            input   wire                            cke,
            
            input   wire                            x_first,
            input   wire                            y_first,
            
            input   wire    signed  [WIDTH-1:0]     dx,
            input   wire    signed  [WIDTH-1:0]     dy_stride,
            input   wire    signed  [WIDTH-1:0]     offset,
            
            output  wire    signed  [WIDTH-1:0]     out_value,
            output  wire                            out_sign
        );
    
    reg     signed  [WIDTH-1:0]     reg_value;
    
    always @(posedge clk) begin
//      if ( reset ) begin
//          reg_value <= {WIDTH{1'b0}};
//      end
//      else 
        if ( cke ) begin
            reg_value <= reg_value + dx;
            if ( x_first ) begin
                reg_value <= reg_value + dy_stride;
                if ( y_first ) begin
                    reg_value <= offset;
                end
            end
        end
    end
    
    assign out_value = reg_value;
    assign out_sign  = out_value[WIDTH-1];
    
endmodule
module jelly_img_gamma_correction_core
        #(
            parameter   S_DATA_WIDTH = 8,
            parameter   M_DATA_WIDTH = 8,
            parameter   RAM_TYPE     = "block"
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            input   wire                        cke,
            
            input   wire                        enable,
            
            input   wire                        mem_clk,
            input   wire                        mem_en,
            input   wire    [S_DATA_WIDTH-1:0]  mem_addr,
            input   wire    [M_DATA_WIDTH-1:0]  mem_din,
            
            input   wire    [S_DATA_WIDTH-1:0]  s_data,
            
            output  wire    [M_DATA_WIDTH-1:0]  m_data
        );
    
    
    // table
    wire    [M_DATA_WIDTH-1:0]  mem_dout;
    jelly_ram_simple_dualport
            #(
                .ADDR_WIDTH     (S_DATA_WIDTH),
                .DATA_WIDTH     (M_DATA_WIDTH),
                .RAM_TYPE       (RAM_TYPE),
                .DOUT_REGS      (1)
            )
        i_ram_simple_dualport
            (
                .wr_clk         (mem_clk),
                .wr_en          (mem_en),
                .wr_addr        (mem_addr),
                .wr_din         (mem_din),
                
                .rd_clk         (clk),
                .rd_en          (cke),
                .rd_regcke      (cke),
                .rd_addr        (s_data),
                .rd_dout        (mem_dout)
            );
    
    reg     [S_DATA_WIDTH-1:0]  st0_data;
    reg     [S_DATA_WIDTH-1:0]  st1_data;
    reg     [M_DATA_WIDTH-1:0]  st2_data;
    always @(posedge clk) begin
        if ( cke ) begin
            st0_data <= s_data;
            st1_data <= st0_data;
            
            if ( enable ) begin
                st2_data <= mem_dout;
            end
            else begin
                if ( M_DATA_WIDTH > S_DATA_WIDTH ) begin
                    st2_data <= (st1_data << (M_DATA_WIDTH - S_DATA_WIDTH)) | (st1_data >> S_DATA_WIDTH);
                end
                else begin
                    st2_data <= (st1_data >> (S_DATA_WIDTH - M_DATA_WIDTH));
                end
           end
        end
    end
    
    assign m_data = st2_data;
    
endmodule
module jelly_img_gaussian_3x3_calc
        #(
            parameter   USER_WIDTH     = 0,
            parameter   DATA_WIDTH     = 8,
            parameter   OUT_DATA_WIDTH = DATA_WIDTH,
            
            // local
            parameter   USER_BITS  = USER_WIDTH > 0 ? USER_WIDTH : 1
        )
        (
            input   wire                            reset,
            input   wire                            clk,
            input   wire                            cke,
            
            input   wire                            enable,
            
            input   wire    [3*3*DATA_WIDTH-1:0]    in_data,
            
            output  wire    [OUT_DATA_WIDTH-1:0]    out_data
        );
    
    wire    [DATA_WIDTH+3:0]    in_data00 = in_data[(3*0+0)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data01 = in_data[(3*0+1)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data02 = in_data[(3*0+2)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data10 = in_data[(3*1+0)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data11 = in_data[(3*1+1)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data12 = in_data[(3*1+2)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data20 = in_data[(3*2+0)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data21 = in_data[(3*2+1)*DATA_WIDTH +: DATA_WIDTH];
    wire    [DATA_WIDTH+3:0]    in_data22 = in_data[(3*2+2)*DATA_WIDTH +: DATA_WIDTH];
    
    reg     [DATA_WIDTH+3:0]    st0_data0;
    reg     [DATA_WIDTH+3:0]    st0_data1;
    reg     [DATA_WIDTH+3:0]    st0_data2;
    reg     [DATA_WIDTH+3:0]    st0_data3;
    reg     [DATA_WIDTH+3:0]    st0_data;
    
    reg     [DATA_WIDTH+3:0]    st1_data0;
    reg     [DATA_WIDTH+3:0]    st1_data1;
    reg     [DATA_WIDTH+3:0]    st1_data;
    
    reg     [DATA_WIDTH+3:0]    st2_data0;
    reg     [DATA_WIDTH+3:0]    st2_data;
    
    reg     [DATA_WIDTH+3:0]    st3_data;
    
    always @(posedge clk) begin
        if ( cke ) begin
            // stage0
            st0_data0   <= (in_data00 + in_data22);
            st0_data1   <= (in_data20 + in_data02);
            st0_data2   <= (in_data01 + in_data21) << 1;
            st0_data3   <= (in_data10 + in_data12) << 1;
            st0_data    <= in_data11 << 2;
            
            // stage1
            st1_data0   <= st0_data0 + st0_data1;
            st1_data1   <= st0_data2 + st0_data3;
            st1_data    <= st0_data;
            
            // stage2
            st2_data0   <= st1_data0 + st1_data1;
            st2_data    <= st1_data;
            
            // stage3
            if ( enable ) begin
                st3_data <= st2_data + st2_data0;
            end
            else begin
                st3_data <= st2_data << 2;
            end
        end
    end
    
    assign out_data = (4 + DATA_WIDTH >= OUT_DATA_WIDTH) ? st3_data >> (4 + DATA_WIDTH - OUT_DATA_WIDTH) :
                                                           st3_data << (OUT_DATA_WIDTH - 4 - DATA_WIDTH);
    
endmodule
module jelly_axi4s_video_combiner
        #(
            parameter   NUM         = 2,
            parameter   TUSER_WIDTH = 1,
            parameter   TDATA_WIDTH = 32,
            parameter   S_REGS      = 1,
            parameter   M_REGS      = 1
        )
        (
            input   wire                            aresetn,
            input   wire                            aclk,
            input   wire                            aclken,
            
            input   wire    [NUM*TUSER_WIDTH-1:0]   s_axi4s_tuser,
            input   wire    [NUM-1:0]               s_axi4s_tlast,
            input   wire    [NUM*TDATA_WIDTH-1:0]   s_axi4s_tdata,
            input   wire    [NUM-1:0]               s_axi4s_tvalid,
            output  wire    [NUM-1:0]               s_axi4s_tready,
            
            output  wire    [NUM*TUSER_WIDTH-1:0]   m_axi4s_tuser,
            output  wire    [NUM-1:0]               m_axi4s_tlast,
            output  wire    [NUM*TDATA_WIDTH-1:0]   m_axi4s_tdata,
            output  wire                            m_axi4s_tvalid,
            input   wire                            m_axi4s_tready
        );
    
    localparam DATA_WIDTH = (TUSER_WIDTH-1) + 1 + TDATA_WIDTH;
    
    genvar  i;
    
    // パケット化
    wire    [NUM-1:0]               s_frame_start;
    wire    [NUM*DATA_WIDTH-1:0]    s_data;
    
    wire                            m_frame_start;
    wire    [NUM*DATA_WIDTH-1:0]    m_data;
    
    generate
    for ( i = 0; i < NUM; i = i+1 ) begin : loop_packet
        assign s_frame_start[i]                   = s_axi4s_tuser[i*TUSER_WIDTH];
        assign s_data[i*DATA_WIDTH +: DATA_WIDTH] = {(s_axi4s_tuser >> 1), s_axi4s_tlast[i], s_axi4s_tdata[i*TDATA_WIDTH +: TDATA_WIDTH]};
        
        assign m_axi4s_tuser[i*TUSER_WIDTH +: TUSER_WIDTH] = {(m_data[i*DATA_WIDTH +: DATA_WIDTH] >> (1+TDATA_WIDTH)), m_frame_start};
        assign m_axi4s_tlast[i]                            = (m_data[i*DATA_WIDTH +: DATA_WIDTH] >> TDATA_WIDTH);
        assign m_axi4s_tdata[i*TDATA_WIDTH +: TDATA_WIDTH] = m_data[i*DATA_WIDTH +: DATA_WIDTH];
    end
    endgenerate
    
    
    jelly_data_frame_combiner
            #(
                .NUM            (NUM),
                .DATA_WIDTH     (DATA_WIDTH),
                .S_REGS         (S_REGS),
                .M_REGS         (M_REGS)
            )
        i_data_frame_combiner
            (
                .reset          (~aresetn),
                .clk            (aclk),
                .cke            (aclken),
                
                .s_frame_start  (s_frame_start),
                .s_data         (s_data),
                .s_valid        (s_axi4s_tvalid),
                .s_ready        (s_axi4s_tready),
                
                .m_frame_start  (m_frame_start),
                .m_data         (m_data),
                .m_valid        (m_axi4s_tvalid),
                .m_ready        (m_axi4s_tready)
            );
    
endmodule
module jelly_jbus_to_wishbone
        #(
            parameter                           ADDR_WIDTH   = 30,
            parameter                           DATA_SIZE    = 2,               // 0:8bit, 1:16bit, 2:32bit ...
            parameter                           DATA_WIDTH   = (8 << DATA_SIZE),
            parameter                           SEL_WIDTH    = (DATA_WIDTH / 8)
        )
        (
            // system
            input   wire                        reset,
            input   wire                        clk,
            
            // slave port (jelly bus)
            input   wire                        s_jbus_en,
            input   wire    [ADDR_WIDTH-1:0]    s_jbus_addr,
            input   wire    [DATA_WIDTH-1:0]    s_jbus_wdata,
            output  wire    [DATA_WIDTH-1:0]    s_jbus_rdata,
            input   wire                        s_jbus_we,
            input   wire    [SEL_WIDTH-1:0]     s_jbus_sel,
            input   wire                        s_jbus_valid,
            output  wire                        s_jbus_ready,
            
            // master port (WISHBONE bus)
            output  wire    [ADDR_WIDTH-1:0]    m_wb_adr_o,
            input   wire    [DATA_WIDTH-1:0]    m_wb_dat_i,
            output  wire    [DATA_WIDTH-1:0]    m_wb_dat_o,
            output  wire                        m_wb_we_o,
            output  wire    [SEL_WIDTH-1:0]     m_wb_sel_o,
            output  wire                        m_wb_stb_o,
            input   wire                        m_wb_ack_i
        );

    reg                         reg_buf_en;
    reg     [DATA_WIDTH-1:0]    reg_buf_rdata;
    reg     [DATA_WIDTH-1:0]    reg_rdata;
    
    always @ ( posedge clk ) begin
        if ( reset ) begin
            reg_buf_en    <= 1'b0;
            reg_buf_rdata <= {DATA_WIDTH{1'bx}};
        end
        else begin
            if ( s_jbus_en ) begin
                reg_rdata  <= reg_buf_en ? reg_buf_rdata : m_wb_dat_i;
                reg_buf_en <= 1'b0;
            end
            else begin
                // 無効中に来たデータを保存
                if ( m_wb_stb_o & m_wb_ack_i ) begin
                    reg_buf_en <= 1'b1;
                end
            end
            
            if ( !reg_buf_en ) begin
                reg_buf_rdata <= m_wb_dat_i;
            end
        end
    end
    
    assign m_wb_adr_o   = s_jbus_addr;
    assign m_wb_dat_o   = s_jbus_wdata;
    assign m_wb_we_o    = s_jbus_we;
    assign m_wb_sel_o   = s_jbus_sel;
    assign m_wb_stb_o   = s_jbus_valid & !reg_buf_en;
    
    assign s_jbus_rdata = reg_rdata;
    assign s_jbus_ready = !m_wb_stb_o | m_wb_ack_i;
    
endmodule
module jelly_jbus_to_ram
        #(
            parameter   ADDR_WIDTH  = 12,
            parameter   DATA_WIDTH  = 32,
            parameter   SEL_WIDTH   = (DATA_WIDTH / 8)
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            
            // jelly bus
            input   wire                        s_jbus_en,
            input   wire    [ADDR_WIDTH-1:0]    s_jbus_addr,
            input   wire    [DATA_WIDTH-1:0]    s_jbus_wdata,
            output  wire    [DATA_WIDTH-1:0]    s_jbus_rdata,
            input   wire                        s_jbus_we,
            input   wire    [SEL_WIDTH-1:0]     s_jbus_sel,
            input   wire                        s_jbus_valid,
            output  wire                        s_jbus_ready,
            
            // ram
            output  wire                        m_ram_en,
            output  wire                        m_ram_we,
            output  wire    [ADDR_WIDTH-1:0]    m_ram_addr,
            output  wire    [DATA_WIDTH-1:0]    m_ram_wdata,
            input   wire    [DATA_WIDTH-1:0]    m_ram_rdata
        );
    
    // write control
    reg                         reg_we;
    reg     [ADDR_WIDTH-1:0]    reg_addr;
    reg     [SEL_WIDTH-1:0]     reg_sel;
    reg     [DATA_WIDTH-1:0]    reg_wdata;
    always @( posedge clk ) begin
        if ( reset ) begin
            reg_we    <= 1'b0;
            reg_sel   <= {SEL_WIDTH{1'bx}};
            reg_wdata <= {DATA_WIDTH{1'bx}};
        end
        else begin
            if ( s_jbus_en & s_jbus_ready ) begin
                reg_we    <= s_jbus_valid & s_jbus_we;
                reg_addr  <= s_jbus_addr;
                reg_sel   <= s_jbus_sel;
                reg_wdata <= s_jbus_wdata;
            end
            else begin
                reg_we    <= 1'b0; 
            end
        end
    end
    
    // write mask
    function [DATA_WIDTH-1:0] make_write_mask;
    input   [SEL_WIDTH-1:0] sel;
    integer                 i, j;
    begin
        for ( i = 0; i < SEL_WIDTH; i = i + 1 ) begin
            for ( j = 0; j < 8; j = j + 1 ) begin
                make_write_mask[i*8 + j] = sel[i];
            end
        end
    end
    endfunction
    
    wire    [DATA_WIDTH-1:0]    write_mask;
    assign write_mask = make_write_mask(reg_sel);
    
    assign s_jbus_rdata = m_ram_rdata;
    assign s_jbus_ready = !(s_jbus_valid & reg_we);
    
    assign m_ram_en     = (s_jbus_en & s_jbus_valid) | reg_we;
    assign m_ram_we     = reg_we;
    assign m_ram_addr   = reg_we ? reg_addr : s_jbus_addr;
    assign m_ram_wdata  = (m_ram_rdata & ~write_mask) | (reg_wdata & write_mask);
    
endmodule
module jelly_wishbone_clk_x2
        #(
            parameter   WB_ADR_WIDTH  = 30,
            parameter   WB_DAT_WIDTH  = 32,
            parameter   WB_SEL_WIDTH  = (WB_DAT_WIDTH / 8)
        )
        (
            //system
            input   wire                        clk,
            input   wire                        clk_x2,
            input   wire                        reset,
            
            // wishbone
            input   wire    [WB_ADR_WIDTH-1:0]  s_wb_adr_i,
            output  reg     [WB_DAT_WIDTH-1:0]  s_wb_dat_o,
            input   wire    [WB_DAT_WIDTH-1:0]  s_wb_dat_i,
            input   wire                        s_wb_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]  s_wb_sel_i,
            input   wire                        s_wb_stb_i,
            output  reg                         s_wb_ack_o,
            
            // wishbone
            output  reg     [WB_ADR_WIDTH-1:0]  m_wb_x2_adr_o,
            output  reg     [WB_DAT_WIDTH-1:0]  m_wb_x2_dat_o,
            input   wire    [WB_DAT_WIDTH-1:0]  m_wb_x2_dat_i,
            output  reg                         m_wb_x2_we_o,
            output  reg     [WB_SEL_WIDTH-1:0]  m_wb_x2_sel_o,
            output  reg                         m_wb_x2_stb_o,
            input   wire                        m_wb_x2_ack_i
        );
    
    reg                         st_idle;
    reg                         st_busy;
    reg                         st_end;

    always @( posedge clk ) begin
        if ( reset ) begin
            s_wb_ack_o <= 1'b0;
        end
        else begin
            if ( s_wb_stb_i & ~s_wb_ack_o & st_end ) begin
                s_wb_ack_o <= 1'b1;
            end
            else begin
                s_wb_ack_o <= 1'b0;
            end
        end
    end
    
    
    always @( posedge clk_x2 ) begin
        if ( reset ) begin
            st_idle <= 1'b1;
            st_busy <= 1'b0;
            st_end  <= 1'b0;
            
            m_wb_x2_adr_o <= {WB_ADR_WIDTH{1'bx}};
            m_wb_x2_dat_o <= {WB_DAT_WIDTH{1'bx}};
            m_wb_x2_we_o  <= 1'bx;
            m_wb_x2_sel_o <= {WB_SEL_WIDTH{1'bx}};
            m_wb_x2_stb_o <= 1'b0;
        end
        else begin
            if ( st_idle ) begin
                if ( s_wb_stb_i & ~s_wb_ack_o ) begin
                    m_wb_x2_adr_o <= s_wb_adr_i;
                    m_wb_x2_dat_o <= s_wb_dat_i;
                    m_wb_x2_we_o  <= s_wb_we_i;
                    m_wb_x2_sel_o <= s_wb_sel_i;
                    m_wb_x2_stb_o <= 1'b1;
                    
                    st_idle <= 1'b0;
                    st_busy <= 1'b1;
                end
            end
            else if ( st_busy ) begin
                s_wb_dat_o <= m_wb_x2_dat_i;
                if ( m_wb_x2_ack_i ) begin
                    m_wb_x2_stb_o <= 1'b0;
                    st_busy     <= 1'b0;
                    st_end      <= 1'b1;
                end
            end
            else if ( st_end ) begin
                if ( s_wb_ack_o ) begin
                    st_end  <= 1'b0;
                    st_idle <= 1'b1;
                end
            end
        end
    end
    
endmodule
module jelly_axi4s_video_width_converter
        #(
            parameter   UNIT_WIDTH    = 8,
            parameter   S_TDATA_SIZE  = 0,   // log2 (0:1byte, 1:2byte, 2:4byte, 3:81byte...)
            parameter   M_TDATA_SIZE  = 0,   // log2 (0:1byte, 1:2byte, 2:4byte, 3:81byte...)
                                                
            parameter   S_TDATA_WIDTH = (UNIT_WIDTH << S_TDATA_SIZE),
            parameter   M_TDATA_WIDTH = (UNIT_WIDTH << M_TDATA_SIZE)
        )
        (
            input   wire                        aresetn,
            input   wire                        aclk,
            input   wire                        aclken,
            
            input   wire                        endian,
            
            input   wire    [0:0]               s_axi4s_tuser,
            input   wire                        s_axi4s_tlast,
            input   wire    [S_TDATA_WIDTH-1:0] s_axi4s_tdata,
            input   wire                        s_axi4s_tvalid,
            output  wire                        s_axi4s_tready,
            
            output  wire    [0:0]               m_axi4s_tuser,
            output  wire                        m_axi4s_tlast,
            output  wire    [M_TDATA_WIDTH-1:0] m_axi4s_tdata,
            output  wire                        m_axi4s_tvalid,
            input   wire                        m_axi4s_tready
        );
    
    
    jelly_data_width_converter
            #(
                .UNIT_WIDTH     (UNIT_WIDTH),
                .S_DATA_SIZE    (S_TDATA_SIZE),
                .M_DATA_SIZE    (M_TDATA_SIZE),
                .INIT_DATA      ({M_TDATA_WIDTH{1'bx}})
            )
        i_data_width_converter_tdata
            (
                .reset          (~aresetn),
                .clk            (aclk),
                .cke            (aclken),
                
                .endian         (endian),
                
                .s_data         (s_axi4s_tdata),
                .s_first        (s_axi4s_tuser),
                .s_last         (s_axi4s_tlast),
                .s_valid        (s_axi4s_tvalid),
                .s_ready        (s_axi4s_tready),
                
                .m_data         (m_axi4s_tdata),
                .m_first        (m_axi4s_tuser),
                .m_last         (m_axi4s_tlast),
                .m_valid        (m_axi4s_tvalid),
                .m_ready        (m_axi4s_tready)
            );
    
    
endmodule
module jelly_wishbone_to_ram
        #(
            parameter   WB_ADR_WIDTH  = 12,
            parameter   WB_DAT_WIDTH  = 32,
            parameter   WB_SEL_WIDTH  = (WB_DAT_WIDTH / 8)
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            
            // wishbone
            input   wire    [WB_ADR_WIDTH-1:0]  s_wb_adr_i,
            output  wire    [WB_DAT_WIDTH-1:0]  s_wb_dat_o,
            input   wire    [WB_DAT_WIDTH-1:0]  s_wb_dat_i,
            input   wire                        s_wb_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]  s_wb_sel_i,
            input   wire                        s_wb_stb_i,
            output  wire                        s_wb_ack_o,
            
            // ram
            output  wire                        m_ram_en,
            output  wire                        m_ram_we,
            output  wire    [WB_ADR_WIDTH-1:0]  m_ram_addr,
            output  wire    [WB_DAT_WIDTH-1:0]  m_ram_wdata,
            input   wire    [WB_DAT_WIDTH-1:0]  m_ram_rdata
        );
    
    
    // write mask
    function [WB_DAT_WIDTH-1:0] make_write_mask;
    input   [WB_SEL_WIDTH-1:0]  sel;
    integer                 i, j;
    begin
        for ( i = 0; i < WB_SEL_WIDTH; i = i + 1 ) begin
            for ( j = 0; j < 8; j = j + 1 ) begin
                make_write_mask[i*8 + j] = sel[i];
            end
        end
    end
    endfunction
    
    wire    [WB_DAT_WIDTH-1:0]  write_mask;
    assign write_mask = make_write_mask(s_wb_sel_i);
    
    reg         reg_ack;
    always @( posedge clk ) begin
        if ( reset ) begin
            reg_ack <= 1'b0;
        end
        else begin
            reg_ack <= !reg_ack & s_wb_stb_i;
        end
    end
    
    assign s_wb_dat_o  = m_ram_rdata;
    assign s_wb_ack_o  = reg_ack;
    
    assign m_ram_en    = s_wb_stb_i;
    assign m_ram_we    = s_wb_we_i & reg_ack;
    assign m_ram_addr  = s_wb_adr_i;
    assign m_ram_wdata = (m_ram_rdata & ~write_mask) | (s_wb_dat_i & write_mask);
    
    
endmodule