dakies/OSS_Verilog huggingface dataset:
module jelly_axi4s_video_fifo
        #(
            parameter   TUSER_WIDTH = 1,
            parameter   TDATA_WIDTH = 32,
            
            parameter   ASYNC       = 1,
            parameter   PTR_WIDTH   = 10,
            parameter   DOUT_REGS   = 1,
            parameter   RAM_TYPE    = "block",
            parameter   LOW_DEALY   = 0,
            parameter   S_REGS      = 1,
            parameter   M_REGS      = 1
        )
        (
            input   wire                        s_axi4s_aresetn,
            input   wire                        s_axi4s_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    [PTR_WIDTH:0]       s_fifo_free_count,
            
            input   wire                        m_axi4s_aresetn,
            input   wire                        m_axi4s_aclk,
            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                        m_axi4s_tvalid,
            input   wire                        m_axi4s_tready,
            output  wire    [PTR_WIDTH:0]       m_fifo_data_count
        );
    
    jelly_fifo_generic_fwtf
            #(
                .ASYNC          (ASYNC),
                .DATA_WIDTH     (TUSER_WIDTH + 1 + TDATA_WIDTH),
                .PTR_WIDTH      (PTR_WIDTH),
                .DOUT_REGS      (DOUT_REGS),
                .RAM_TYPE       (RAM_TYPE),
                .LOW_DEALY      (LOW_DEALY),
                .SLAVE_REGS     (S_REGS),
                .MASTER_REGS    (M_REGS)
            )
        i_fifo_generic_fwtf
            (
                .s_reset       (~s_axi4s_aresetn),
                .s_clk         (s_axi4s_aclk),
                .s_data        ({s_axi4s_tuser, s_axi4s_tlast, s_axi4s_tdata}),
                .s_valid       (s_axi4s_tvalid),
                .s_ready       (s_axi4s_tready),
                .s_free_count  (s_fifo_free_count),
                
                .m_reset       (~m_axi4s_aresetn),
                .m_clk         (m_axi4s_aclk),
                .m_data        ({m_axi4s_tuser, m_axi4s_tlast, m_axi4s_tdata}),
                .m_valid       (m_axi4s_tvalid),
                .m_ready       (m_axi4s_tready),
                .m_data_count  (m_fifo_data_count)
            );
    
    
endmodule
module jelly_wishbone_arbiter
        #(
            parameter                           WB_ADR_WIDTH = 30,
            parameter                           WB_DAT_WIDTH = 32,
            parameter                           WB_SEL_WIDTH = (WB_DAT_WIDTH / 8)
        )
        (
            // system
            input   wire                        reset,
            input   wire                        clk,
            
            // cpu side port 0
            input   wire    [WB_ADR_WIDTH-1:0]  s_wb0_adr_i,
            input   wire    [WB_DAT_WIDTH-1:0]  s_wb0_dat_i,
            output  wire    [WB_DAT_WIDTH-1:0]  s_wb0_dat_o,
            input   wire                        s_wb0_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]  s_wb0_sel_i,
            input   wire                        s_wb0_stb_i,
            output  wire                        s_wb0_ack_o,
            
            // cpu side port 1
            input   wire    [WB_ADR_WIDTH-1:0]  s_wb1_adr_i,
            input   wire    [WB_DAT_WIDTH-1:0]  s_wb1_dat_i,
            output  wire    [WB_DAT_WIDTH-1:0]  s_wb1_dat_o,
            input   wire                        s_wb1_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]  s_wb1_sel_i,
            input   wire                        s_wb1_stb_i,
            output  wire                        s_wb1_ack_o,
            
            // memory side port
            output  wire    [WB_ADR_WIDTH-1:0]  m_wb_adr_o,
            input   wire    [WB_DAT_WIDTH-1:0]  m_wb_dat_i,
            output  wire    [WB_DAT_WIDTH-1:0]  m_wb_dat_o,
            output  wire                        m_wb_we_o,
            output  wire    [WB_SEL_WIDTH-1:0]  m_wb_sel_o,
            output  wire                        m_wb_stb_o,
            input   wire                        m_wb_ack_i
        );
    
    
    // arbiter
    reg         reg_busy;
    reg         reg_sw;
    wire        sw;
    always @ ( posedge clk ) begin
        if ( reset ) begin
            reg_busy <= 1'b0;
            reg_sw   <= 1'bx;
        end
        else begin
            reg_busy <= m_wb_stb_o & !m_wb_ack_i;
            
            if ( !reg_busy ) begin
                reg_sw <= sw;
            end
        end
    end
    assign sw = reg_busy ? reg_sw : !s_wb0_stb_i;
    
    
    assign m_wb_adr_o = sw ? s_wb1_adr_i : s_wb0_adr_i;
    assign m_wb_dat_o = sw ? s_wb1_dat_i : s_wb0_dat_i;
    assign m_wb_we_o  = sw ? s_wb1_we_i  : s_wb0_we_i;
    assign m_wb_sel_o = sw ? s_wb1_sel_i : s_wb0_sel_i;
    assign m_wb_stb_o = sw ? s_wb1_stb_i : s_wb0_stb_i;
    
    assign s_wb0_dat_o = m_wb_dat_i;
    assign s_wb0_ack_o = !sw ? m_wb_ack_i : 1'b0;
    
    assign s_wb1_dat_o = m_wb_dat_i;
    assign s_wb1_ack_o = sw ? m_wb_ack_i : 1'b0;
    
endmodule
module jelly_axi4s_debug_monitor
        #(
            parameter   TUSER_WIDTH = 1,
            parameter   TDATA_WIDTH = 24,
            parameter   TIMER_WIDTH = 32,
            parameter   FRAME_WIDTH = 32,
            parameter   PIXEL_WIDTH = 32,
            parameter   X_WIDTH     = 16,
            parameter   Y_WIDTH     = 16
        )
        (
            input   wire                            aresetn,
            input   wire                            aclk,
            input   wire                            aclken,
            
            input   wire    [TUSER_WIDTH-1:0]       axi4s_tuser,
            input   wire                            axi4s_tlast,
            input   wire    [TDATA_WIDTH-1:0]       axi4s_tdata,
            input   wire                            axi4s_tvalid,
            input   wire                            axi4s_tready
        );
    
    
    (* MARK_DEBUG = "true" *)   reg     [TUSER_WIDTH-1:0]   dbg_axi4s_tuser;
    (* MARK_DEBUG = "true" *)   reg                         dbg_axi4s_tlast;
    (* MARK_DEBUG = "true" *)   reg     [TDATA_WIDTH-1:0]   dbg_axi4s_tdata;
    (* MARK_DEBUG = "true" *)   reg                         dbg_axi4s_tvalid;
    (* MARK_DEBUG = "true" *)   reg                         dbg_axi4s_tready;
    
    (* MARK_DEBUG = "true" *)   reg     [TIMER_WIDTH-1:0]   dbg_timer;
    (* MARK_DEBUG = "true" *)   reg     [PIXEL_WIDTH-1:0]   dbg_pixel;
    (* MARK_DEBUG = "true" *)   reg     [FRAME_WIDTH-1:0]   dbg_frame;
    (* MARK_DEBUG = "true" *)   reg     [X_WIDTH-1:0]       dbg_x;
    (* MARK_DEBUG = "true" *)   reg     [Y_WIDTH-1:0]       dbg_y;
    (* MARK_DEBUG = "true" *)   reg     [X_WIDTH-1:0]       dbg_width;
    (* MARK_DEBUG = "true" *)   reg     [Y_WIDTH-1:0]       dbg_height;
    
    always @(posedge aclk) begin
        dbg_axi4s_tuser  <= axi4s_tuser;
        dbg_axi4s_tlast  <= axi4s_tlast;
        dbg_axi4s_tdata  <= axi4s_tdata;
        dbg_axi4s_tvalid <= axi4s_tvalid;
        dbg_axi4s_tready <= axi4s_tready;
    end
    
    always @(posedge aclk) begin
        if ( ~aresetn ) begin
            dbg_timer  <= 0;
            dbg_pixel  <= 0;
            dbg_frame  <= 0;
            dbg_x      <= 0;
            dbg_y      <= 0;
            dbg_width  <= 0;
            dbg_height <= 0;
        end
        else if ( aclken ) begin
            dbg_timer <= dbg_timer + 1;
            
            if ( axi4s_tvalid && axi4s_tready ) begin
                dbg_pixel <= dbg_pixel + 1;
                dbg_x     <= dbg_x     + 1;
                
                if ( axi4s_tlast ) begin
                    dbg_x     <= 0;
                    dbg_y     <= dbg_y + 1;
                    dbg_width <= dbg_x + 1;
                end
                
                if ( axi4s_tuser[0] ) begin
                    dbg_frame  <= dbg_frame + 1;
                    dbg_pixel  <= 0;
    //              dbg_x      <= 0;
                    dbg_y      <= 0;
                    dbg_height <= dbg_y;
                end
            end
        end
    end
    
    
endmodule
module jelly_regfile64_w1r2
        #(
            parameter   DATA_WIDTH  = 32,
            parameter   WRITE_FIRST = 1,
            parameter   ZERO_REGS   = 0,
            parameter   DEVICE      = "RTL"
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            input   wire                        cke,
            
            input   wire                        wr_en,
            input   wire    [5:0]               wr_addr,
            input   wire    [DATA_WIDTH-1:0]    wr_data,
            
            input   wire    [5:0]               rd0_addr,
            output  reg     [DATA_WIDTH-1:0]    rd0_data,
            
            input   wire    [5:0]               rd1_addr,
            output  reg     [DATA_WIDTH-1:0]    rd1_data
        );
    
    wire    [DATA_WIDTH-1:0]    ram_data0;
    wire    [DATA_WIDTH-1:0]    ram_data1;
    
    jelly_ram64x1d_w1r2
            #(
                .WIDTH      (DATA_WIDTH),
                .DEVICE     (DEVICE)
            )
        i_ram64x1d_w1r2
            (
                .clk        (clk),
                
                .wr_en      (wr_en & cke),
                .wr_addr    (wr_addr),
                .wr_data    (wr_data),
                
                .rd0_addr   (rd0_addr),
                .rd0_data   (ram_data0),
                
                .rd1_addr   (rd1_addr),
                .rd1_data   (ram_data1)
            );
    
    
    always @(posedge clk) begin
        if ( reset ) begin
            rd0_data <= {DATA_WIDTH{1'b0}};
            rd1_data <= {DATA_WIDTH{1'b0}};
        end
        else if ( cke ) begin
            rd0_data <= ram_data0;
            rd1_data <= ram_data1;
            
            if ( WRITE_FIRST ) begin
                if ( wr_en && wr_addr == rd0_addr ) begin
                    rd0_data <= wr_data;
                end
                
                if ( wr_en && wr_addr == rd1_addr ) begin
                    rd1_data <= wr_data;
                end
            end
            
            if ( ZERO_REGS ) begin
                if ( rd0_addr == 5'd0 ) begin
                    rd0_data <= {DATA_WIDTH{1'b0}};
                end
                
                if ( rd1_addr == 5'd0 ) begin
                    rd1_data <= {DATA_WIDTH{1'b0}};
                end
            end
        end
    end
    
    
endmodule
module jelly_jbus_master_model
        #(
            parameter   ADR_WIDTH  = 12,
            parameter   DAT_SIZE   = 2,     // 2^n (0:8bit, 1:16bit, 2:32bit ...)
            parameter   DAT_WIDTH  = (8 << DAT_SIZE),
            parameter   SEL_WIDTH  = (1 << DAT_SIZE),
            parameter   TABLE_FILE = "",
            parameter   TABLE_SIZE = 256
        )
        (
            // system
            input   wire                        clk,
            input   wire                        reset,
            
            // wishbone
            output  wire    [ADR_WIDTH-1:0]     m_wb_adr_o,
            output  wire    [DAT_WIDTH-1:0]     m_wb_dat_o,
            input   wire    [DAT_WIDTH-1:0]     m_wb_dat_i,
            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
        );
    
    
    integer     index;
    initial begin
        index = 0;
    end
    
    localparam DAT_POS     = 0;
    localparam SEL_POS     = DAT_POS + DAT_WIDTH;
    localparam ADR_POS     = SEL_POS + SEL_WIDTH;
    localparam WE_POS      = ADR_POS + ADR_WIDTH;
    localparam STB_POS     = WE_POS  + 1;
    localparam END_POS     = STB_POS + 1;
    localparam TABLE_WIDTH = END_POS + 1;
    
    reg     [TABLE_WIDTH-1:0]   test_table  [0:TABLE_SIZE-1];
    initial begin
        $readmemb(TABLE_FILE, test_table);
    end
    
    wire    [TABLE_WIDTH-1:0]   test_pattern;
    assign test_pattern = test_table[index];
    wire    [DAT_WIDTH-1:0]     test_dat;
    assign test_dat = test_pattern[DAT_POS +: DAT_WIDTH];
    
    
    assign m_wb_stb_o = test_pattern[STB_POS];
    assign m_wb_we_o  = test_pattern[WE_POS];
    assign m_wb_adr_o = test_pattern[ADR_POS +: ADR_WIDTH];
    assign m_wb_sel_o = test_pattern[SEL_POS +: SEL_WIDTH];
    assign m_wb_dat_o = test_dat; //m_wb_we_o ? test_table[index][DAT_POS +: DAT_WIDTH] : {DAT_WIDTH{1'bx}};
    
    function cmp_data;
    input   [DAT_WIDTH-1:0] dat;
    input   [DAT_WIDTH-1:0] exp;
    integer                 i;
    begin
        cmp_data = 1'b1;
        for ( i = 0; i < DAT_WIDTH; i = i + 1 ) begin
            if ( exp[i] !== 1'bx && !(dat[i] == exp[i]) ) begin
                cmp_data = 1'b0;
            end
        end
    end
    endfunction
    
    always @ ( posedge clk ) begin
        if ( reset ) begin
            index <= 0;
        end
        else begin
            if ( !m_wb_stb_o | m_wb_ack_i ) begin
                if ( !test_table[index][END_POS] ) begin
                    index <= index + 1;
                end
            end
            if ( !m_wb_we_o & m_wb_stb_o & m_wb_ack_i ) begin
                if ( !cmp_data(m_wb_dat_i, test_table[index][DAT_POS +: DAT_WIDTH]) ) begin
                    $display("%t read error", $time);
                end
            end
        end
    end
    
    
endmodule
module jelly_img_record_model
        #(
            parameter   COMPONENT_NUM    = 3,
            parameter   DATA_WIDTH       = 8,
            parameter   INIT_FRAME_NUM   = 0,
            parameter   FRAME_WIDTH      = 32,
            parameter   X_WIDTH          = 32,
            parameter   Y_WIDTH          = 32,
            parameter   FILE_NAME        = "img_%04d.ppm",
            parameter   MAX_PATH         = 64
        )
        (
            input   wire                                    reset,
            input   wire                                    clk,
            input   wire                                    cke,
            
            input   wire    [X_WIDTH-1:0]                   param_width,
            input   wire    [Y_WIDTH-1:0]                   param_height,
            
            input   wire                                    s_img_line_first,
            input   wire                                    s_img_line_last,
            input   wire                                    s_img_pixel_first,
            input   wire                                    s_img_pixel_last,
            input   wire                                    s_img_de,
            input   wire    [COMPONENT_NUM*DATA_WIDTH-1:0]  s_img_data,
            input   wire                                    s_img_valid
        );
    
    
    jelly_axi4s_slave_model
            #(
                .COMPONENT_NUM      (COMPONENT_NUM),
                .DATA_WIDTH         (DATA_WIDTH),
                .INIT_FRAME_NUM     (INIT_FRAME_NUM),
                .FRAME_WIDTH        (FRAME_WIDTH),
                .X_WIDTH            (X_WIDTH),
                .Y_WIDTH            (Y_WIDTH),
                .FILE_NAME          (FILE_NAME),
                .MAX_PATH           (MAX_PATH)
            )
        i_axi4s_slave_model
            (
                .aresetn            (~reset),
                .aclk               (clk),
                .aclken             (cke),
                
                .param_width        (param_width),
                .param_height       (param_height),
                
                .s_axi4s_tuser      (s_img_valid & s_img_line_first & s_img_pixel_first),
                .s_axi4s_tlast      (s_img_valid & s_img_pixel_last),
                .s_axi4s_tdata      (s_img_data),
                .s_axi4s_tvalid     (s_img_valid & s_img_de),
                .s_axi4s_tready     ()
            );
    
    
endmodule
module jelly_wishbone_master_model
        #(
            parameter   ADR_WIDTH  = 12,
            parameter   DAT_SIZE   = 2,     // 2^n (0:8bit, 1:16bit, 2:32bit ...)
            parameter   DAT_WIDTH  = (8 << DAT_SIZE),
            parameter   SEL_WIDTH  = (1 << DAT_SIZE),
            parameter   TABLE_FILE = "",
            parameter   TABLE_SIZE = 256
        )
        (
            // system
            input   wire                        clk,
            input   wire                        reset,
            
            // wishbone
            output  wire    [ADR_WIDTH-1:0]     m_wb_adr_o,
            output  wire    [DAT_WIDTH-1:0]     m_wb_dat_o,
            input   wire    [DAT_WIDTH-1:0]     m_wb_dat_i,
            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
        );
    
    
    integer     index;
    initial begin
        index = 0;
    end
    
    localparam DAT_POS     = 0;
    localparam SEL_POS     = DAT_POS + DAT_WIDTH;
    localparam ADR_POS     = SEL_POS + SEL_WIDTH;
    localparam WE_POS      = ADR_POS + ADR_WIDTH;
    localparam STB_POS     = WE_POS  + 1;
    localparam END_POS     = STB_POS + 1;
    localparam TABLE_WIDTH = END_POS + 1;
    
    reg     [TABLE_WIDTH-1:0]   test_table  [0:TABLE_SIZE-1];
    initial begin
        $readmemb(TABLE_FILE, test_table);
    end
    
    wire    [TABLE_WIDTH-1:0]   test_pattern;
    assign test_pattern = test_table[index];
    wire    [DAT_WIDTH-1:0]     test_dat;
    assign test_dat = test_pattern[DAT_POS +: DAT_WIDTH];
    
    
    assign m_wb_stb_o = test_pattern[STB_POS];
    assign m_wb_we_o  = test_pattern[WE_POS];
    assign m_wb_adr_o = test_pattern[ADR_POS +: ADR_WIDTH];
    assign m_wb_sel_o = test_pattern[SEL_POS +: SEL_WIDTH];
    assign m_wb_dat_o = m_wb_we_o ? test_dat : {DAT_WIDTH{1'bx}};
    
    function cmp_data;
    input   [DAT_WIDTH-1:0] dat;
    input   [DAT_WIDTH-1:0] exp;
    integer                 i;
    begin
        cmp_data = 1'b1;
        for ( i = 0; i < DAT_WIDTH; i = i + 1 ) begin
            if ( exp[i] !== 1'bx && !(dat[i] == exp[i]) ) begin
                cmp_data = 1'b0;
            end
        end
    end
    endfunction
    
    always @ ( posedge clk ) begin
        if ( reset ) begin
            index <= 0;
        end
        else begin
            if ( !m_wb_stb_o | m_wb_ack_i ) begin
                if ( !test_table[index][END_POS] ) begin
                    index <= index + 1;
                end
            end
            if ( !m_wb_we_o & m_wb_stb_o & m_wb_ack_i ) begin
                if ( !cmp_data(m_wb_dat_i, test_dat) ) begin
                    $display("%t read error", $time);
                end
            end
        end
    end
    
    
endmodule
module jelly_wishbone_logger
        #(
            parameter   ADR_WIDTH      = 12,
            parameter   DAT_SIZE       = 2,     // 2^n (0:8bit, 1:16bit, 2:32bit ...)
            parameter   DAT_WIDTH      = (8 << DAT_SIZE),
            parameter   SEL_WIDTH      = (DAT_WIDTH / 8),
            parameter   WRITE_LOG_FILE = "",
            parameter   READ_LOG_FILE  = "",
            parameter   DISPLAY        = 1,
            parameter   MESSAGE        = "[wishbone]"
        )
        (
            // system
            input   wire                        clk,
            input   wire                        reset,
            
            // wishbone
            input   wire    [ADR_WIDTH-1:0]     wb_adr_o,
            input   wire    [DAT_WIDTH-1:0]     wb_dat_o,
            input   wire    [DAT_WIDTH-1:0]     wb_dat_i,
            input   wire                        wb_we_o,
            input   wire    [SEL_WIDTH-1:0]     wb_sel_o,
            input   wire                        wb_stb_o,
            input   wire                        wb_ack_i            
        );
    
    
    integer                     file;
    
    initial begin
        if ( WRITE_LOG_FILE != "" ) begin
            file = $fopen(WRITE_LOG_FILE);
            $fclose(file);
        end
        if ( READ_LOG_FILE != "" ) begin
            file = $fopen(READ_LOG_FILE);
            $fclose(file);
        end
    end
    
    always @(posedge clk) begin
        if ( !reset ) begin
            // write
            if ( wb_stb_o & wb_we_o & wb_ack_i ) begin
                if ( DISPLAY ) begin
                    $display("w %h %h %h %d %s", wb_adr_o, wb_dat_o, wb_sel_o, $time, MESSAGE);
                end
                if ( WRITE_LOG_FILE != "" ) begin
                    file = $fopen(WRITE_LOG_FILE, "a");
                    $fdisplay(file, "w %h %h %h %d %s", wb_adr_o, wb_dat_o, wb_sel_o, $time, MESSAGE);
                    $fclose(file);
                end
            end
            
            // read
            if ( wb_stb_o & !wb_we_o & wb_ack_i ) begin
                if ( DISPLAY ) begin
                    $display("r %h %h %h %d %s", wb_adr_o, wb_dat_i, wb_sel_o, $time, MESSAGE);
                end
                if ( READ_LOG_FILE != "" ) begin
                    file = $fopen(READ_LOG_FILE, "a");
                    $fdisplay(file, "r %h %h %h %d %s", wb_adr_o, wb_dat_i, wb_sel_o, $time, MESSAGE);
                    $fclose(file);
                end
            end
            
        end
    end
    
endmodule
module jelly_cpu_adder
        #(
            parameter                           DATA_WIDTH = 32
        )
        (
            input   wire    [DATA_WIDTH-1:0]    in_data0,
            input   wire    [DATA_WIDTH-1:0]    in_data1,
            input   wire                        in_carry,
            
            output  wire    [DATA_WIDTH-1:0]    out_data,
            
            output  wire                        out_carry,
            output  wire                        out_overflow,
            output  wire                        out_negative,
            output  wire                        out_zero
        );
    
    // add
    wire                        msb_carry;
    assign {msb_carry, out_data[DATA_WIDTH-2:0]} = in_data0[DATA_WIDTH-2:0] + in_data1[DATA_WIDTH-2:0] + in_carry;
    
    // add MSB
    assign {out_carry, out_data[DATA_WIDTH-1]} = in_data0[DATA_WIDTH-1] + in_data1[DATA_WIDTH-1] + msb_carry;
    
    // overflow
    assign out_overflow = (msb_carry != out_carry);
    
    // negative
    assign out_negative = out_data[DATA_WIDTH-1];
    
    // zero
    assign out_zero = (out_data == {DATA_WIDTH{1'b0}});
    
endmodule
module jelly_cpu_memdec
        (
            input   wire    [31:0]      in_rdata,
            input   wire    [1:0]       in_size,
            input   wire                in_unsigned,
            input   wire    [3:0]       in_mask,
            input   wire    [1:0]       in_shift,
            input   wire    [31:0]      in_rt_data,
            
            output  wire    [31:0]      out_rdata
        );
        
    reg     [31:0]      tmp_rdata;
    
    always @* begin
        tmp_rdata = in_rdata;
        
        // rotation
        case ( in_shift )
        2'b00: tmp_rdata = tmp_rdata[31:0];
        2'b01: tmp_rdata = {tmp_rdata[7:0], tmp_rdata[31:8]};
        2'b10: tmp_rdata = {tmp_rdata[15:0], tmp_rdata[31:16]};
        2'b11: tmp_rdata = {tmp_rdata[23:0], tmp_rdata[31:24]};
        endcase
        
        // mask
        if ( !in_mask[0] ) begin tmp_rdata[7:0]   = in_rt_data[7:0];   end
        if ( !in_mask[1] ) begin tmp_rdata[15:8]  = in_rt_data[15:8];  end
        if ( !in_mask[2] ) begin tmp_rdata[23:16] = in_rt_data[23:16]; end
        if ( !in_mask[3] ) begin tmp_rdata[31:24] = in_rt_data[31:24]; end
        
        if ( in_size == 2'b00 ) begin
            // byte
            tmp_rdata[31:8]  = in_unsigned ? {24{1'b0}} : {24{tmp_rdata[7]}};
        end
        else if ( in_size == 2'b01 ) begin
            // harf-word
            tmp_rdata[31:16] = in_unsigned ? {16{1'b0}} : {16{tmp_rdata[15]}};
        end
    end
        
    assign out_rdata = tmp_rdata;
        
endmodule
module jelly_cpu_alu
        #(
            parameter                           DATA_SIZE  = 5,         // 3:8bit, 4:16bit, 5:32bit, ...
            parameter                           DATA_WIDTH = (1 << DATA_SIZE)
        )
        (
            input   wire                        op_adder_en,
            input   wire    [1:0]               op_adder_func,

            input   wire                        op_logic_en,
            input   wire    [1:0]               op_logic_func,
            
            input   wire                        op_comp_en,
            input   wire    [1:0]               op_comp_func,
            
            input   wire    [DATA_WIDTH-1:0]    in_data0,
            input   wire    [DATA_WIDTH-1:0]    in_data1,
            
            output  wire    [DATA_WIDTH-1:0]    out_data,
            output  wire                        out_carry,
            output  wire                        out_overflow,
            output  wire                        out_negative,
            output  wire                        out_zero
        );
    
    // adder
    wire    [DATA_WIDTH-1:0]    adder_in_data0;
    wire    [DATA_WIDTH-1:0]    adder_in_data1;
    wire                        adder_in_carry;
    wire    [DATA_WIDTH-1:0]    adder_out_data;
    
    assign adder_in_data0 = in_data0;
    assign adder_in_data1 = (op_adder_func[0] ? ~in_data1 : in_data1) &
                            (op_adder_func[1] ? {DATA_WIDTH{1'b0}} : {DATA_WIDTH{1'b1}});
    
    assign adder_in_carry = (op_adder_func == `ALU_ADDER_FUNC_SUB) ? 1'b1 : 1'b0;
    
    jelly_cpu_adder
        i_cpu_adder
            (
                .in_data0       (adder_in_data0),
                .in_data1       (adder_in_data1),
                .in_carry       (adder_in_carry),
            
                .out_data       (adder_out_data),
            
                .out_carry      (out_carry),
                .out_overflow   (out_overflow),
                .out_negative   (out_negative),
                .out_zero       (out_zero)
            );
    
    
    // logic
    wire    [DATA_WIDTH-1:0]    logic_out_data;
    assign logic_out_data = (op_logic_func == `ALU_LOGIC_FUNC_AND) ?  (in_data0 & in_data1) : {DATA_WIDTH{1'b0}}
                            | (op_logic_func == `ALU_LOGIC_FUNC_OR)  ?  (in_data0 | in_data1) : {DATA_WIDTH{1'b0}}
                            | (op_logic_func == `ALU_LOGIC_FUNC_XOR) ?  (in_data0 ^ in_data1) : {DATA_WIDTH{1'b0}}
                            | (op_logic_func == `ALU_LOGIC_FUNC_NOR) ? ~(in_data0 | in_data1) : {DATA_WIDTH{1'b0}};
    
    // compare
    wire    [DATA_WIDTH-1:0]    comp_out_data;
    assign comp_out_data[0] = (op_comp_func == `ALU_COMP_FUNC_SLT) ? (out_negative != out_overflow) : ~out_carry;
    assign comp_out_data[DATA_WIDTH-1:1] = 0;
    
    // output
    assign out_data = op_adder_en ? adder_out_data : {DATA_WIDTH{1'b0}}
                    | op_logic_en ? logic_out_data : {DATA_WIDTH{1'b0}}
                    | op_comp_en  ? comp_out_data  : {DATA_WIDTH{1'b0}};
    
    
endmodule
module jelly_cpu_shifter
        #(
            parameter                           SA_WIDTH   = 5,
            parameter                           DATA_WIDTH = (1 << SA_WIDTH)
        )
        (
            input   wire    [1:0]               op_func,
            
            input   wire    [DATA_WIDTH-1:0]    in_data,
            input   wire    [SA_WIDTH-1:0]      in_sa,
            
            output  wire    [DATA_WIDTH-1:0]    out_data
        );
    
    // shifter
    wire    [DATA_WIDTH-1:0]    data_extend;
    assign data_extend = op_func[1] ? {DATA_WIDTH{in_data[DATA_WIDTH-1]}} : {DATA_WIDTH{1'b0}};
    assign out_data    = op_func[0] ? ({data_extend, in_data} >> in_sa) : (in_data << in_sa);
    
endmodule
module jelly_shift
        #(
            parameter   SHIFT_WIDTH  = 5,
            parameter   DATA_WIDTH   = 32
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            input   wire                        cke,

            input   wire                        left,
            input   wire                        rotation,
            input   wire                        arithmetic,
            input   wire                        shift_signed,
            
            input   wire    [SHIFT_WIDTH-1:0]   shift,
            input   wire    [DATA_WIDTH-1:0]    din,
            output  reg     [DATA_WIDTH-1:0]    dout
        );
    
    wire            [SHIFT_WIDTH-1:0]   ushift = shift;
    wire    signed  [SHIFT_WIDTH-1:0]   sshift = shift;

    wire            [DATA_WIDTH-1:0]    udata  = din;
    wire    signed  [DATA_WIDTH-1:0]    sdata  = din;
    
    localparam  ROT_NUM   = ((1 << SHIFT_WIDTH) + DATA_WIDTH + (DATA_WIDTH-1)) / DATA_WIDTH;
    localparam  ROT_SHIFT = (ROT_NUM - 1) * DATA_WIDTH;
    
    always @* begin
        dout = {DATA_WIDTH{1'bx}};
        
        casex ( {rotation, shift_signed, left, arithmetic} )
        4'b0000: dout = (udata >>  ushift);
        4'b0001: dout = (sdata >>> ushift);
        4'b0010: dout = (udata <<  ushift);
        4'b0011: dout = (sdata <<< ushift);
        
        4'b0100: dout = ((sshift >= 0) ? (udata >>  sshift) : (udata <<  -sshift));
        4'b0101: dout = ((sshift >= 0) ? (sdata >>> sshift) : (sdata <<< -sshift));
        4'b0110: dout = ((sshift >= 0) ? (udata <<  sshift) : (udata >>  -sshift));
        4'b0111: dout = ((sshift >= 0) ? (sdata <<< sshift) : (sdata >>> -sshift));

        4'b100x: dout = ({ROT_NUM{udata}} >> ushift);
        4'b101x: dout = (({ROT_NUM{udata}} << ushift) >> ROT_SHIFT);
        4'b110x: dout = ((sshift >= 0) ? ({ROT_NUM{udata}} >> sshift) : (({ROT_NUM{udata}} << ushift) >> ROT_SHIFT));
        4'b111x: dout = ((sshift >= 0) ? (({ROT_NUM{udata}} << ushift) >> ROT_SHIFT) : ({ROT_NUM{udata}} >> sshift));
        default: dout = {DATA_WIDTH{1'bx}};
        endcase
    end
    
endmodule
module jelly_fifo_fwtf2
        #(
            parameter   DATA_WIDTH  = 8,
            parameter   PTR_WIDTH   = 10,
            parameter   DOUT_REGS   = 0,
            parameter   RAM_TYPE    = "block",
            parameter   MASTER_REGS = 1
        )
        (
            // system
            input   wire                        reset,
            input   wire                        clk,
            
            // slave
            input   wire    [DATA_WIDTH-1:0]    s_data,
            input   wire                        s_valid,
            output  wire                        s_ready,
            output  wire    [PTR_WIDTH:0]       s_free_count,
            
            // master
            output  wire    [DATA_WIDTH-1:0]    m_data,
            output  wire                        m_valid,
            input   wire                        m_ready,
            output  wire    [PTR_WIDTH:0]       m_data_count
        );
    
    
    
    wire    [PTR_WIDTH:0]       write_ptr;
    
    wire                        s_read_ready;
    
    wire    [PTR_WIDTH:0]       read_ptr;
    
    wire                        fifo_full;
    wire                        fifo_empty;
    wire    [PTR_WIDTH:0]       fifo_free_count;
    wire    [PTR_WIDTH:0]       fifo_data_count;
    
    
    jelly_fifo_ra_fwtf
            #(
                .DATA_WIDTH         (DATA_WIDTH),
                .ADDR_WIDTH         (PTR_WIDTH),
                .DOUT_REGS          (DOUT_REGS),
                .RAM_TYPE           (RAM_TYPE),
                .MASTER_REGS        (MASTER_REGS)
            )
        i_fifo_ra_fwtf
            (
                .reset              (reset),
                .clk                (clk),
                
                .s_write_addr       (write_ptr),
                .s_write_data       (s_data),
                .s_write_valid      (s_valid),
                .s_write_ready      (s_ready),
                
                .write_ptr          (write_ptr),
                .write_ptr_next     (write_ptr + 1'b1),
                .write_ptr_update   (s_valid & s_ready),
                
                
                .s_read_addr        (read_ptr),
                .s_read_valid       (!fifo_empty),
                .s_read_ready       (s_read_ready),
                
                .m_read_data        (m_data),
                .m_read_valid       (m_valid),
                .m_read_ready       (m_ready),
                .m_read_data_count  (m_data_count),
                                     
                .read_ptr           (read_ptr),
                .read_ptr_next      (read_ptr + 1'b1),
                .read_ptr_update    (!fifo_empty && s_read_ready),
                                     
                .fifo_full          (fifo_full),
                .fifo_empty         (fifo_empty),
                .fifo_free_count    (fifo_free_count),
                .fifo_data_count    (fifo_data_count)
            );
    
    assign s_free_count = fifo_free_count;
    
    
endmodule
module jelly_shift_register
        #(
            parameter   SEL_WIDTH = 5,
            parameter   NUM       = (1 << SEL_WIDTH)
        )
        (
            input   wire                        clk,
            input   wire                        cke,
            
            input   wire    [SEL_WIDTH-1:0]     sel,
            input   wire                        in_data,
            output  wire                        out_data
        );
    
    reg     [NUM-1:0]   reg_shift;
    
    always @(posedge clk) begin
        if ( cke ) begin
            reg_shift <= {reg_shift, in_data};
        end
    end
    
    assign out_data = reg_shift[sel];
    
endmodule
module jelly_data_shifter
        #(
            parameter   SEL_WIDTH  = 5,
            parameter   NUM        = (1 << SEL_WIDTH),
            parameter   DATA_WIDTH = 8
        )
        (
            input   wire                        clk,
            input   wire                        cke,
            
            input   wire    [SEL_WIDTH-1:0]     sel,
            input   wire    [DATA_WIDTH-1:0]    in_data,
            output  wire    [DATA_WIDTH-1:0]    out_data
        );
    
    
    /*
    reg     [NUM*DATA_WIDTH-1:0]    reg_data;
    always @(posedge clk) begin
        if ( cke ) begin
            reg_data <= {reg_data, in_data};
        end
    end
    
    assign out_data = reg_data[sel*DATA_WIDTH +: DATA_WIDTH];
    */
    
    
    genvar      i;
    
    generate
    for ( i = 0; i < DATA_WIDTH; i = i+1 ) begin : loop_shift
        jelly_shift_register
                #(
                    .SEL_WIDTH      (SEL_WIDTH),
                    .NUM            (NUM)
                )
            i_shift_register
                (
                    .clk            (clk),
                    .cke            (cke),
                    
                    .sel            (sel),
                    .in_data        (in_data[i]),
                    .out_data       (out_data[i])
                );
    end
    endgenerate
    
    
    
endmodule
module jelly_graycode_to_binary
        #(
            parameter                       WIDTH = 4
        )
        (
            input   wire    [WIDTH-1:0]     graycode,
            output  reg     [WIDTH-1:0]     binary
        );
    
    integer i;
    always @* begin
        binary[WIDTH-1] = graycode[WIDTH-1];
        for ( i = WIDTH - 2; i >= 0; i = i - 1 ) begin
            binary[i] = binary[i+1] ^ graycode[i];
        end
    end
    
endmodule
module jelly_binary_to_graycode
        #(
            parameter                       WIDTH = 4
        )
        (
            input   wire    [WIDTH-1:0]     binary,
            output  reg     [WIDTH-1:0]     graycode
        );
    
    integer i;
    always @* begin
        graycode[WIDTH-1] = binary[WIDTH-1];
        for ( i = WIDTH - 2; i >= 0; i = i-1 ) begin
            graycode[i] = binary[i+1] ^ binary[i];
        end
    end
    
    /*
    function [WIDTH-1:0] gray_out;
    input   [WIDTH-1:0] bin_in;
    integer i;
        begin
            gray_out[WIDTH-1] = bin_in[WIDTH-1];
            for ( i = WIDTH-2; i >= 0; i = i-1 ) begin
                gray_out[i] = bin_in[i+1] ^ bin_in[i];
            end
        end
    endfunction
    
    assign graycode = gray_out(binary);
    */
    
endmodule
module jelly_data_linear_expand
        #(
            parameter   NUM            = 1,
            parameter   IN_DATA_WIDTH  = 8,
            parameter   OUT_DATA_WIDTH = 12
        )
        (
            input   wire    [NUM*IN_DATA_WIDTH-1:0]     din,
            output  wire    [NUM*OUT_DATA_WIDTH-1:0]    dout
        );
    
    genvar      i;
    
    generate
    for ( i = 0; i < NUM; i = i+1 ) begin : loop_unit
        jelly_data_linear_expand_unit
                #(
                    .IN_DATA_WIDTH      (IN_DATA_WIDTH),
                    .OUT_DATA_WIDTH     (OUT_DATA_WIDTH)
                )
            i_data_linear_expand_unit
                (
                    .din                (din [i*IN_DATA_WIDTH  +: IN_DATA_WIDTH]),
                    .dout               (dout[i*OUT_DATA_WIDTH +: OUT_DATA_WIDTH])
                );
    end
    endgenerate
    
endmodule
module jelly_data_linear_expand_unit
        #(
            parameter   IN_DATA_WIDTH  = 8,
            parameter   OUT_DATA_WIDTH = 12
        )
        (
            input   wire    [IN_DATA_WIDTH-1:0]     din,
            output  wire    [OUT_DATA_WIDTH-1:0]    dout
        );

    genvar      i;
    generate
    for ( i = 0; i < OUT_DATA_WIDTH; i = i+1 ) begin : loop_bit
        assign dout[OUT_DATA_WIDTH-1 - i] = din[IN_DATA_WIDTH-1 - (i % IN_DATA_WIDTH)];
    end
    endgenerate
    
endmodule
module jelly_bus_shift
        #(
            parameter   SHIFT_WIDTH   = 4,
            parameter   NUM           = (1 << SHIFT_WIDTH),
            parameter   DATA_WIDTH    = 8,
            
            parameter   LEFT          = 0,
            parameter   ARITHMETIC    = 0,      // <- 使わない？
            parameter   ROTATION      = 0,
            
            parameter   USE_PRIMITIVE = 0,
            parameter   DEVICE        = "7SERIES" // "RTL"
        )
        (
            input   wire    [SHIFT_WIDTH-1:0]       shift,
            input   wire    [NUM*DATA_WIDTH-1:0]    in_data,
            output  wire    [NUM*DATA_WIDTH-1:0]    out_data
        );
    
    genvar      i, j;
    
    generate
    for ( i = 0; i < DATA_WIDTH; i = i+1 ) begin : loop_shift
        wire    [NUM-1:0]   in_bus;
        wire    [NUM-1:0]   out_bus;
        
        for ( j = 0; j < NUM; j = j+1 ) begin : loop_in_bus
            assign in_bus[j] = in_data[j*DATA_WIDTH + i];
        end
        
        jelly_bit_shift
                #(
                    .SHIFT_WIDTH    (SHIFT_WIDTH),
                    .DATA_WIDTH     (NUM),
                    
                    .LEFT           (LEFT),
                    .ARITHMETIC     (ARITHMETIC),
                    .ROTATION       (ROTATION),
                    
                    .USE_PRIMITIVE  (USE_PRIMITIVE),
                    .DEVICE         (DEVICE)
                )
            i_bit_shift
                (
                    .shift          (shift),
                    .in_data        (in_bus),
                    .out_data       (out_bus)
                );
        
        for ( j = 0; j < NUM; j = j+1 ) begin : loop_out_bus
            assign out_data[j*DATA_WIDTH + i] = out_bus[j];
        end
    end
    endgenerate
    
    
endmodule
module jelly_param_update_master
        #(
            parameter   INDEX_WIDTH = 1
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            input   wire                        cke,
            
            input   wire                        in_index,
            
            output  wire                        out_ack,
            output  wire    [INDEX_WIDTH-1:0]   out_index
        );
    
    // parameter latch
    (* ASYNC_REG="true" *)  reg     [INDEX_WIDTH-1:0]   ff0_index, ff1_index;
    always @(posedge clk) begin
        ff0_index <= in_index;
        ff1_index <= ff0_index;
    end
    
    reg     [INDEX_WIDTH-1:0]   reg_index;
    reg                         reg_ack;
    always @(posedge clk) begin
        if ( reset ) begin
            reg_index <= {INDEX_WIDTH{1'b0}};
            reg_ack   <= 1'b0;
        end
        else if ( cke ) begin
            reg_index <= ff1_index;
            reg_ack   <= (reg_index != ff1_index);
        end
    end
    
    assign out_ack    = reg_ack;
    assign out_index  = reg_index;
    
endmodule
module jelly_minmax_unit
        #(
            parameter   INDEX_WIDTH = 5,
            parameter   USER_WIDTH  = 32,
            parameter   DATA_WIDTH  = 32,
            parameter   DATA_SIGNED = 1,
            parameter   CMP_MIN     = 0,        // minかmaxか
            parameter   CMP_EQ      = 0         // 同値のとき data0 と data1 どちらを優先するか
        )
        (
            input   wire                                clk,
            input   wire                                cke,
            
            input   wire    [INDEX_WIDTH-1:0]           in_index0,
            input   wire    [USER_WIDTH-1:0]            in_user0,
            input   wire    [DATA_WIDTH-1:0]            in_data0,
            input   wire                                in_en0,
            
            input   wire    [INDEX_WIDTH-1:0]           in_index1,
            input   wire    [USER_WIDTH-1:0]            in_user1,
            input   wire    [DATA_WIDTH-1:0]            in_data1,
            input   wire                                in_en1,
            
            output  wire    [INDEX_WIDTH-1:0]           out_index,
            output  wire    [USER_WIDTH-1:0]            out_user,
            output  wire    [DATA_WIDTH-1:0]            out_data,
            output  wire                                out_en
        );
    
    // 符号付きに拡張
    wire    signed  [DATA_WIDTH:0]  data0 = DATA_SIGNED ? {in_data0[DATA_WIDTH-1], in_data0} : {1'b0, in_data0};
    wire    signed  [DATA_WIDTH:0]  data1 = DATA_SIGNED ? {in_data1[DATA_WIDTH-1], in_data1} : {1'b0, in_data1};
    reg                             tmp_sel;
    
    reg     [INDEX_WIDTH-1:0]       reg_index;
    reg     [USER_WIDTH-1:0]        reg_user;
    reg     [DATA_WIDTH-1:0]        reg_data;
    reg                             reg_en;
    
    always @(posedge clk) begin
        if ( cke ) begin
            // 選択
            if ( in_en0 && in_en1 ) begin
                if ( CMP_EQ ) begin
                    tmp_sel = CMP_MIN ? (data1 <= data0) : (data1 >= data0);
                end
                else begin
                    tmp_sel = CMP_MIN ? (data1 <  data0) : (data1 >  data0);
                end
            end
            else if ( in_en0 && !in_en1 ) begin
                tmp_sel = 0;
            end
            else if ( !in_en0 && in_en1 ) begin
                tmp_sel = 1;
            end
            reg_index <= tmp_sel ? in_index1 : in_index0;
            reg_user  <= tmp_sel ? in_user1  : in_user0;
            reg_data  <= tmp_sel ? in_data1  : in_data0;
            
            if ( !in_en0 && !in_en1 ) begin
                reg_index <= {INDEX_WIDTH{1'bx}};
                reg_user  <= {USER_WIDTH{1'bx}};
                reg_data  <= {DATA_WIDTH{1'bx}};
            end
            
            reg_en <= (in_en0 | in_en1);
        end
    end
    
    assign out_index = reg_index;
    assign out_user  = reg_user;
    assign out_data  = reg_data;
    assign out_en    = reg_en;
    
endmodule
module jelly_data_ff
        #(
            parameter   DATA_WIDTH = 8,
            parameter   S_REGS     = 1,
            parameter   M_REGS     = 1,
            
            parameter   DATA_BITS  = DATA_WIDTH > 0 ? DATA_WIDTH : 1,
            parameter   INIT_DATA  = {DATA_BITS{1'bx}}
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            input   wire                        cke,
            
            // slave port
            input   wire    [DATA_BITS-1:0]     s_data,
            input   wire                        s_valid,
            output  wire                        s_ready,
            
            // master port
            output  wire    [DATA_BITS-1:0]     m_data,
            output  wire                        m_valid,
            input   wire                        m_ready
        );
    
    
    jelly_pipeline_insert_ff
            #(
                .DATA_WIDTH     (DATA_BITS),
                .SLAVE_REGS     (S_REGS),
                .MASTER_REGS    (M_REGS),
                .INIT_DATA      (INIT_DATA)
            )
        i_pipeline_insert_ff
            (
                .reset          (reset),
                .clk            (clk),
                .cke            (cke),
                
                .s_data         (s_data),
                .s_valid        (s_valid),
                .s_ready        (s_ready),
                
                .m_data         (m_data),
                .m_valid        (m_valid),
                .m_ready        (m_ready),
                
                .buffered       (),
                .s_ready_next   ()
            );
    
    
endmodule
module jelly_register_wishbone
        #(
            parameter   DATA_WIDTH    = 32,
            parameter   INITIAL_VALUE = 0,
            parameter   WB_DAT_WIDTH  = DATA_WIDTH,
            parameter   WB_SEL_WIDTH  = (WB_DAT_WIDTH / 8)
        )
        (
            // system
            input   wire                        clk,
            input   wire                        reset,
            
            input   wire    [WB_DAT_WIDTH-1:0]  readonly_mask,
            
            // wishbone
            output  wire    [WB_DAT_WIDTH-1:0]  wb_dat_o,
            input   wire    [WB_DAT_WIDTH-1:0]  wb_dat_i,
            input   wire                        wb_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]  wb_sel_i,
            input   wire                        wb_stb_i,
            output  wire                        wb_ack_o,
            
            // data port
            input   wire    [WB_DAT_WIDTH-1:0]  data_we,
            input   wire    [WB_DAT_WIDTH-1:0]  data_in,
            output  wire    [WB_DAT_WIDTH-1:0]  data_out
        );
    
    // register
    reg     [DATA_WIDTH-1:0]    reg_data;
    
    reg     [DATA_WIDTH-1:0]    reg_data_next;
    
    
    // register
    always @ ( posedge clk ) begin
        if ( reset ) begin
            reg_data <= INITIAL_VALUE;
        end
        else begin
            reg_data <= reg_data_next;
        end
    end
    
    
    integer                     i, j;
    always @* begin
        reg_data_next = reg_data;
        
        // wishbone
        for ( i = 0; i < WB_SEL_WIDTH; i = i + 1 ) begin
            if ( wb_stb_i & wb_we_i & wb_sel_i[i] ) begin
                for ( j = 0; j < 8; j = j + 1 ) begin
                    if ( !readonly_mask[i*8+j] & (i*8+j < DATA_WIDTH) ) begin
                        reg_data_next[i*8+j] = wb_dat_i[i*8+j];
                    end
                end
            end
        end
        
        // data
        for ( i = 0; i < DATA_WIDTH; i = i + 1 ) begin
            if ( data_we[i] ) begin
                reg_data_next[i] = data_in[i];
            end
        end
    end
    
    assign wb_dat_o = wb_stb_i ? reg_data_next : {WB_DAT_WIDTH{1'b0}};
    assign wb_ack_o = wb_stb_i;
    
endmodule
module jelly_selector
        #(
            parameter   SEL_WIDTH = 2,
            parameter   OUT_WIDTH = 8,
            parameter   IN_WIDTH  = (OUT_WIDTH * SEL_WIDTH)
        )
        (
            input   wire    [SEL_WIDTH-1:0]     sel,
            input   wire    [IN_WIDTH-1:0]      din,
            output  reg     [OUT_WIDTH-1:0]     dout
        );
    
    integer i;
    integer j;
    always @* begin
        dout = {OUT_WIDTH{1'b0}};
        for ( i = 0; i < SEL_WIDTH; i = i + 1 ) begin
            if ( sel[i] ) begin
                for ( j = 0; j < OUT_WIDTH; j = j + 1 ) begin
                    dout[j] = dout[j] | din[OUT_WIDTH*i + j];
                end
            end
        end
    end
    
endmodule