data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v
1: b'%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:20: Operator ADD expects 20 bits on the RHS, but RHS\'s VARREF \'address\' generates 16 bits.\n                                                                                                 : ... In instance processor\nassign o_addr = alt ? {segment[15:0], 4\'h0} + address : {r_cs[15:0], 4\'h0} + current;\n                                            ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:20: Operator ADD expects 20 bits on the RHS, but RHS\'s VARREF \'current\' generates 16 bits.\n                                                                                                 : ... In instance processor\nassign o_addr = alt ? {segment[15:0], 4\'h0} + address : {r_cs[15:0], 4\'h0} + current;\n                                                                           ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:35: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                                                 : ... In instance processor\nreg     [2:0]   state = 1\'b0;                         \n                        ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:42: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS\'s CONST \'2\'h0\' generates 2 bits.\n                                                                                                 : ... In instance processor\nreg     [2:0]   icp = 2\'h0;                           \n                      ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:43: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                                                 : ... In instance processor\nreg     [2:0]   length = 1\'b0;                        \n                         ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:47: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                                                 : ... In instance processor\nreg     [2:0]   segment_override_num = 1\'b0;          \n                                       ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:215: Operator ADD expects 3 bits on the RHS, but RHS\'s SEL generates 1 bits.\n                                                                                                  : ... In instance processor\n            8\'b1000_00xx, 8\'b1100_011x: length = (modrm_length + icache[0]) + 1\'b1;\n                                                               ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:313: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b000: w_op1 = icache[0] ? r_ax : r_ax[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:314: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b001: w_op1 = icache[0] ? r_cx : r_cx[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:315: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b010: w_op1 = icache[0] ? r_dx : r_dx[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:316: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b011: w_op1 = icache[0] ? r_bx : r_bx[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:317: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b100: w_op1 = icache[0] ? r_sp : r_ax[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:318: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b101: w_op1 = icache[0] ? r_bp : r_cx[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:319: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b110: w_op1 = icache[0] ? r_si : r_dx[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:320: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b111: w_op1 = icache[0] ? r_di : r_bx[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:327: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b000: w_op2 = icache[0] ? r_ax : r_ax[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:328: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b001: w_op2 = icache[0] ? r_cx : r_cx[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:329: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b010: w_op2 = icache[0] ? r_dx : r_dx[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:330: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b011: w_op2 = icache[0] ? r_bx : r_bx[7:0];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:331: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b100: w_op2 = icache[0] ? r_sp : r_ax[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:332: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b101: w_op2 = icache[0] ? r_bp : r_cx[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:333: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b110: w_op2 = icache[0] ? r_si : r_dx[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:334: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n        3\'b111: w_op2 = icache[0] ? r_di : r_bx[15:8];\n                                  ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:343: Operator ADD expects 16 bits on the RHS, but RHS\'s VARREF \'length\' generates 3 bits.\n                                                                                                  : ... In instance processor\n    n_ip = r_ip + length;\n                ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:365: Operator ASSIGNDLY expects 3 bits on the Assign RHS, but Assign RHS\'s CONST \'2\'h3\' generates 2 bits.\n                                                                                                  : ... In instance processor\n            segment_override_num <= 2\'b11;  \n                                 ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:366: Operator ASSIGNDLY expects 1 bits on the Assign RHS, but Assign RHS\'s CONST \'2\'h0\' generates 2 bits.\n                                                                                                  : ... In instance processor\n            prefix_0F            <= 2\'b0;\n                                 ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:408: Operator ADD expects 16 bits on the RHS, but RHS\'s CONST \'2\'h2\' generates 2 bits.\n                                                                                                  : ... In instance processor\n            current <= current + 2\'h2;\n                               ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:437: Operator ADD expects 16 bits on the RHS, but RHS\'s CONST \'3\'h6\' generates 3 bits.\n                                                                                                  : ... In instance processor\n        current <= (r_ip + 3\'h6);    \n                         ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:521: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n                _op1    <= i_data[15:8];\n                        ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:534: Operator COND expects 16 bits on the Conditional True, but Conditional True\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n            _op1  <= address[0] ? i_data[15:8] : i_data[7:0];\n                                ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/version.1.x8086/processor.rev5.v:534: Operator COND expects 16 bits on the Conditional False, but Conditional False\'s SEL generates 8 bits.\n                                                                                                  : ... In instance processor\n            _op1  <= address[0] ? i_data[15:8] : i_data[7:0];\n                                ^\n%Error: Exiting due to 31 warning(s)\n'
module processor(

    input   wire            clock,
    input   wire            locked,
    input   wire            m_ready,
    output  wire    [19:0]  o_addr,
    input   wire    [15:0]  i_data,
    output  wire     [15:0]  o_data,
    output  reg             o_wr

);

`define I_FETCH             3'h0
`define I_DECODE            3'h1
`define I_READ_DATA         3'h2
`define I_READ_DATA_WIDE    3'h3
`define I_EXECUTE           3'h4

assign o_addr = alt ? {segment[15:0], 4'h0} + address : {r_cs[15:0], 4'h0} + current;
assign o_data = r_ax;







reg [47:0] icache;

reg             prefix_0F = 1'b0;
reg             has_prefixed;
reg             has_modrm_byte;

reg     [2:0]   state = 1'b0;
reg             alt = 1'b0;
reg     [15:0]  segment;
reg     [15:0]  address;
reg     [15:0]  current = 16'h0;
reg             wsize;
reg             target;
reg     [2:0]   icp = 2'h0;
reg     [2:0]   length = 1'b0;
reg     [2:0]   modrm_length;
reg             instruction_done = 1'b1;
reg             segment_override = 1'b0;
reg     [2:0]   segment_override_num = 1'b0;
wire    [7:0]   modrm_byte = prefix_0F ? icache[23:16] : icache[15:8];


wire    [15:0]  op1 = target ? _op2 : _op1;
wire    [15:0]  op2 = target ? _op1 : _op2;






always @* begin



    
    casex (icache[7:0])

        8'b001x_x110,
        8'b0110_01xx,
        8'b1001_1011,
        8'b1111_0000,
        8'b1001_001x,
        8'b0000_1111:
        
            has_prefixed = 1'b1;
            
        default:
        
            has_prefixed = 1'b0;

    endcase





    

    if (icache[7:0] == 8'h0F)

        casex(icache[15:8])
        
            8'b0000_01xx, 8'b0000_10xx, 8'b0000_11x0,
            8'b0011_0xxx, 8'b0011_10x1, 8'b0011_11xx,
            8'b0111_0111, 8'b0111_100x,
            8'b1000_xxxx,
            8'b1011_000x, 8'b1011_0010, 8'b1011_011x, 8'b1011_100x, 8'b1011_1010,
            8'b1101_1xxx,
            8'b1111_1111:
            
                has_modrm_byte = 1'b0;
                
            default:
            
                has_modrm_byte = 1'b1;

        endcase
    

    else
    

        casex(icache[7:0]) 
        
            8'b00_xxx0xx,
            8'b10_00xxxx,
            8'b11_00000x,
            8'b11_0001xx,
            8'b11_0100xx,
            8'b11_011xxx,
            8'b11_11x11x:
            
                has_modrm_byte = 1'b1;
                
            default:
            
                has_modrm_byte = 1'b0;
        
        endcase
       
end





reg     [15:0]  r_ip = 16'h0000;
reg     [15:0]  n_ip = 16'h0000;
reg     [15:0]  r_ax = 16'h0000;
reg     [15:0]  r_bx = 16'h0000;
reg     [15:0]  r_cx = 16'h0000;
reg     [15:0]  r_dx = 16'h0000;
reg     [15:0]  r_sp = 16'h0000;
reg     [15:0]  r_bp = 16'h0000;
reg     [15:0]  r_si = 16'h0000;
reg     [15:0]  r_di = 16'h0000;
reg     [15:0]  r_es = 16'h0000;
reg     [15:0]  r_cs = 16'h0000;
reg     [15:0]  r_ss = 16'h0000;
reg     [15:0]  r_ds = 16'h0000;
reg     [15:0]  r_fs = 16'h0000;
reg     [15:0]  r_gs = 16'h0000;





always @* begin


    if (has_prefixed) begin

        length = 3'h1;        
    
    end

    else if (has_modrm_byte) begin
    
        casex (modrm_byte)

            8'b00_xxx_110: modrm_length = 3'h4;
            8'b00_xxx_xxx: modrm_length = 3'h2;
            8'b01_xxx_xxx: modrm_length = 3'h3;
            8'b10_xxx_xxx: modrm_length = 3'h4;
            8'b11_xxx_xxx: modrm_length = 3'h2;

        endcase
        


        casex (icache[7:0])
        
            8'b1000_00xx, 8'b1100_011x: length = (modrm_length + icache[0]) + 1'b1;


            default: length = modrm_length;
        
        endcase    

    end
    

    else length = 3'h1;

end




wire    [15:0]  si_bx = r_si + r_bx;
wire    [15:0]  di_bx = r_di + r_bx;
wire    [15:0]  si_bp = r_si + r_bp;
wire    [15:0]  di_bp = r_si + r_bp;

reg     [15:0]  p_addr;
reg     [15:0]  p_segment;

reg     [15:0]  e_address;
reg     [15:0]  e_segment;

reg     [15:0]  w_op1; reg [15:0] _op1;
reg     [15:0]  w_op2; reg [15:0] _op2;

reg     alu_enable;
reg     immediate_size;
reg     operand_is_immediate;


always @* begin
    

    case (segment_override_num) 

        3'h0: p_segment = r_es;
        3'h1: p_segment = r_cs;
        3'h2: p_segment = r_ss;
        3'h3: p_segment = r_ds;
        3'h4: p_segment = r_fs;
        3'h5: p_segment = r_gs;

    endcase    
    

    casex (modrm_byte[7:0]) 


        8'b00_xxx_11x: e_segment = segment_override ? p_segment : r_ds;
        8'bxx_xxx_x0x: e_segment = segment_override ? p_segment : r_ds;
    

        8'bxx_xxx_110: e_segment = segment_override ? p_segment : r_ss;
        8'bxx_xxx_01x: e_segment = segment_override ? p_segment : r_ss;
    
    endcase


    casex (modrm_byte[7:0]) 

        8'bxx_xxx_000: p_addr = si_bx;
        8'bxx_xxx_001: p_addr = di_bx;
        8'bxx_xxx_010: p_addr = si_bp;
        8'bxx_xxx_011: p_addr = di_bp;
        8'bxx_xxx_100: p_addr = r_si;
        8'bxx_xxx_101: p_addr = r_di;
        8'b00_xxx_110: p_addr = icache[31:16];
        8'bxx_xxx_110: p_addr = r_bp;
        8'bxx_xxx_111: p_addr = r_bx;
    
    endcase
    

    casex (modrm_byte[7:0]) 
    

        8'b01_xxx_xxx: e_address = p_addr + {{8{icache[23]}}, icache[23:16]}; 

        8'b10_xxx_xxx: e_address = p_addr + icache[31:16];
        default:       e_address = p_addr;

    endcase
    

    



    

    case (modrm_byte[2:0])
    
        3'b000: w_op1 = icache[0] ? r_ax : r_ax[7:0];
        3'b001: w_op1 = icache[0] ? r_cx : r_cx[7:0];
        3'b010: w_op1 = icache[0] ? r_dx : r_dx[7:0];
        3'b011: w_op1 = icache[0] ? r_bx : r_bx[7:0];
        3'b100: w_op1 = icache[0] ? r_sp : r_ax[15:8];
        3'b101: w_op1 = icache[0] ? r_bp : r_cx[15:8];
        3'b110: w_op1 = icache[0] ? r_si : r_dx[15:8];
        3'b111: w_op1 = icache[0] ? r_di : r_bx[15:8];
    
    endcase
    

    case (modrm_byte[5:3])
    
        3'b000: w_op2 = icache[0] ? r_ax : r_ax[7:0];
        3'b001: w_op2 = icache[0] ? r_cx : r_cx[7:0];
        3'b010: w_op2 = icache[0] ? r_dx : r_dx[7:0];
        3'b011: w_op2 = icache[0] ? r_bx : r_bx[7:0];
        3'b100: w_op2 = icache[0] ? r_sp : r_ax[15:8];
        3'b101: w_op2 = icache[0] ? r_bp : r_cx[15:8];
        3'b110: w_op2 = icache[0] ? r_si : r_dx[15:8];
        3'b111: w_op2 = icache[0] ? r_di : r_bx[15:8];
    
    endcase

end


always @* begin

    n_ip = r_ip + length;
        
end





always @(posedge clock) begin

    case (state)    
    



    
    `I_FETCH: begin
    

        if (instruction_done) begin
            
            segment_override     <= 1'b0;
            segment_override_num <= 2'b11;
            prefix_0F            <= 2'b0;
            operand_is_immediate <= 1'b0;
            immediate_size       <= 1'b0;
            alu_enable           <= 1'b0;
        
        end
        

        instruction_done <= 1'b0;
        



        if (current[0]) begin
        
            case (icp) 
            
                3'h0: begin icache[7:0]   <= i_data[15:8]; end
                3'h1: begin icache[15:8]  <= i_data[15:8]; end
                3'h2: begin icache[23:16] <= i_data[15:8]; end
                3'h3: begin icache[31:24] <= i_data[15:8]; end
                3'h4: begin icache[39:32] <= i_data[15:8]; end
                3'h5: begin icache[47:40] <= i_data[15:8]; state <= `I_DECODE; end
            
            endcase

            current <= current + 1'b1;
            icp     <= icp + 1'b1;
        
        end else begin
        
            case (icp)
            
                3'h0: begin icp <= 3'h2; icache[15:0]  <= i_data[15:0]; end
                3'h1: begin icp <= 3'h3; icache[23:8]  <= i_data[15:0]; end
                3'h2: begin icp <= 3'h4; icache[31:16] <= i_data[15:0]; end
                3'h3: begin icp <= 3'h5; icache[39:24] <= i_data[15:0]; end
                3'h4: begin icp <= 3'h0; icache[47:32] <= i_data[15:0]; state <= `I_DECODE; end
                3'h5: begin icp <= 3'h0; icache[47:40] <= i_data[ 7:0]; state <= `I_DECODE; end    
            
            endcase
                    
            current <= current + 2'h2;
            icp     <= icp + 2'h2;

        end
    
    end
    



    
    `I_DECODE: begin
    



        case (length)
        
            3'h1: begin icp <= 3'h5; icache[39:0] <= icache[47:8];  end
            3'h2: begin icp <= 3'h4; icache[31:0] <= icache[47:16]; end
            3'h3: begin icp <= 3'h3; icache[23:0] <= icache[47:24]; end
            3'h4: begin icp <= 3'h2; icache[15:0] <= icache[47:32]; end
            3'h5: begin icp <= 3'h1; icache[ 7:0] <= icache[47:40]; end
            3'h6: begin icp <= 3'h0; end

        endcase



        current <= (r_ip + 3'h6);
        r_ip    <= n_ip;
        


    



            

        



        if (has_prefixed) begin
        
            state <= `I_FETCH;
            casex (icache[7:0])
            
                8'b0000_1111: prefix_0F <= 1'b1;
            

                8'b001x_x110: begin segment_override <= 1'b1; segment_override_num <= {1'b0,icache[4:3]}; end
                

                8'b0110_010x: begin segment_override <= 1'b1; segment_override_num <= {1'b1,icache[1:0]}; end
                


            endcase        
        
        end    

        else if (has_modrm_byte) begin
        

            instruction_done <= 1'b1;



            _op1    <= w_op1;
            _op2    <= w_op2;
            target  <= icache[1];
            

            if (modrm_byte[7:6] != 2'b11) begin
            
                alt     <= 1'b1;
                wsize   <= icache[0];
                segment <= e_segment;
                address <= e_address;
                state   <= `I_READ_DATA;
            
            end else begin

                state  <= `I_EXECUTE;
                
            end
        
        end

        else begin

            state <= `I_EXECUTE;
            
        end

    end    






    `I_READ_DATA: begin
    

        if (wsize) begin

            if (address[0]) begin
            
                state   <= `I_READ_DATA_WIDE;            
                address <= address + 1'h1;             
                _op1    <= i_data[15:8];

            end else begin

                state   <= `I_EXECUTE;
                _op1    <= i_data[15:0];

            end        


        end else begin

            state <= `I_EXECUTE;
            _op1  <= address[0] ? i_data[15:8] : i_data[7:0];

        end

    end
    

    `I_READ_DATA_WIDE: begin 
    
        state       <= `I_EXECUTE;
        _op1[15:8]  <= i_data[7:0];
        address     <= address - 1'h1;

    end
    
    `I_EXECUTE: begin
    
        state <= `I_FETCH;
    
    end

    endcase
end

endmodule
module processor(

    input   wire            clock,
    input   wire            locked,
    input   wire            m_ready,
    output  wire    [19:0]  o_addr,
    input   wire    [15:0]  i_data,
    output  wire     [15:0]  o_data,
    output  reg             o_wr

);


`define I_FETCH             3'h0
`define I_DECODE            3'h1
`define I_READ_DATA         3'h2
`define I_READ_DATA_WIDE    3'h3
`define I_EXECUTE           3'h4

assign o_addr = alt ? {segment[15:0], 4'h0} + address : {r_cs[15:0], 4'h0} + current;
assign o_data = r_ax;







reg [47:0] icache;

reg             prefix_0F = 1'b0;
reg             has_prefixed;
reg             has_modrm_byte;

reg     [2:0]   state = 1'b0;
reg             alt = 1'b0;
reg     [15:0]  segment;
reg     [15:0]  address;
reg     [15:0]  current = 16'h0;
reg             wsize;
reg             target;
reg     [2:0]   icp = 2'h0;
reg     [2:0]   length = 1'b0;
reg     [2:0]   modrm_length;
reg             instruction_done = 1'b1;
reg             segment_override = 1'b0;
reg     [2:0]   segment_override_num = 1'b0;
wire    [7:0]   modrm_byte = prefix_0F ? icache[23:16] : icache[15:8];


wire    [15:0]  op1 = target ? _op2 : _op1;
wire    [15:0]  op2 = target ? _op1 : _op2;






always @* begin



    
    casex (icache[7:0])

        8'b001x_x110,
        8'b0110_01xx,
        8'b1001_1011,
        8'b1111_0000,
        8'b1001_001x,
        8'b0000_1111:
        
            has_prefixed = 1'b1;
            
        default:
        
            has_prefixed = 1'b0;

    endcase





    

    if (icache[7:0] == 8'h0F)

        casex(icache[15:8])
        
            8'b0000_01xx, 8'b0000_10xx, 8'b0000_11x0,
            8'b0011_0xxx, 8'b0011_10x1, 8'b0011_11xx,
            8'b0111_0111, 8'b0111_100x,
            8'b1000_xxxx,
            8'b1011_000x, 8'b1011_0010, 8'b1011_011x, 8'b1011_100x, 8'b1011_1010,
            8'b1101_1xxx,
            8'b1111_1111:
            
                has_modrm_byte = 1'b0;
                
            default:
            
                has_modrm_byte = 1'b1;

        endcase
    

    else
    

        casex(icache[7:0]) 
        
            8'b00_xxx0xx,
            8'b10_00xxxx,
            8'b11_00000x,
            8'b11_0001xx,
            8'b11_0100xx,
            8'b11_011xxx,
            8'b11_11x11x:
            
                has_modrm_byte = 1'b1;
                
            default:
            
                has_modrm_byte = 1'b0;
        
        endcase
       
end





reg     [15:0]  r_ip = 16'h0000;
reg     [15:0]  n_ip = 16'h0000;
reg     [15:0]  r_ax = 16'h0000;
reg     [15:0]  r_bx = 16'h0000;
reg     [15:0]  r_cx = 16'h0000;
reg     [15:0]  r_dx = 16'h0000;
reg     [15:0]  r_sp = 16'h0000;
reg     [15:0]  r_bp = 16'h0000;
reg     [15:0]  r_si = 16'h0000;
reg     [15:0]  r_di = 16'h0000;
reg     [15:0]  r_es = 16'h0000;
reg     [15:0]  r_cs = 16'h0000;
reg     [15:0]  r_ss = 16'h0000;
reg     [15:0]  r_ds = 16'h0000;
reg     [15:0]  r_fs = 16'h0000;
reg     [15:0]  r_gs = 16'h0000;





always @* begin


    if (has_prefixed) begin

        length = 3'h1;        
    
    end

    else if (has_modrm_byte) begin
    
        casex (modrm_byte)

            8'b00_xxx_110: modrm_length = 3'h4;
            8'b00_xxx_xxx: modrm_length = 3'h2;
            8'b01_xxx_xxx: modrm_length = 3'h3;
            8'b10_xxx_xxx: modrm_length = 3'h4;
            8'b11_xxx_xxx: modrm_length = 3'h2;

        endcase
        


        casex (icache[7:0])
        
            8'b1000_00xx, 8'b1100_011x: length = (modrm_length + icache[0]) + 1'b1;


            default: length = modrm_length;
        
        endcase    

    end
    

    else length = 3'h1;

end




wire    [15:0]  si_bx = r_si + r_bx;
wire    [15:0]  di_bx = r_di + r_bx;
wire    [15:0]  si_bp = r_si + r_bp;
wire    [15:0]  di_bp = r_si + r_bp;

reg     [15:0]  p_addr;
reg     [15:0]  p_segment;

reg     [15:0]  e_address;
reg     [15:0]  e_segment;

reg     [15:0]  w_op1; reg [15:0] _op1;
reg     [15:0]  w_op2; reg [15:0] _op2;

reg     alu_enable;
reg     immediate_size;
reg     operand_is_immediate;


always @* begin
    

    case (segment_override_num) 

        3'h0: p_segment = r_es;
        3'h1: p_segment = r_cs;
        3'h2: p_segment = r_ss;
        3'h3: p_segment = r_ds;
        3'h4: p_segment = r_fs;
        3'h5: p_segment = r_gs;

    endcase    
    

    casex (modrm_byte[7:0]) 


        8'b00_xxx_11x: e_segment = segment_override ? p_segment : r_ds;
        8'bxx_xxx_x0x: e_segment = segment_override ? p_segment : r_ds;
    

        8'bxx_xxx_110: e_segment = segment_override ? p_segment : r_ss;
        8'bxx_xxx_01x: e_segment = segment_override ? p_segment : r_ss;
    
    endcase


    casex (modrm_byte[7:0]) 

        8'bxx_xxx_000: p_addr = si_bx;
        8'bxx_xxx_001: p_addr = di_bx;
        8'bxx_xxx_010: p_addr = si_bp;
        8'bxx_xxx_011: p_addr = di_bp;
        8'bxx_xxx_100: p_addr = r_si;
        8'bxx_xxx_101: p_addr = r_di;
        8'b00_xxx_110: p_addr = icache[31:16];
        8'bxx_xxx_110: p_addr = r_bp;
        8'bxx_xxx_111: p_addr = r_bx;
    
    endcase
    

    casex (modrm_byte[7:0]) 
    

        8'b01_xxx_xxx: e_address = p_addr + {{8{icache[23]}}, icache[23:16]}; 

        8'b10_xxx_xxx: e_address = p_addr + icache[31:16];
        default:       e_address = p_addr;

    endcase
    

    



    

    case (modrm_byte[2:0])
    
        3'b000: w_op1 = icache[0] ? r_ax : r_ax[7:0];
        3'b001: w_op1 = icache[0] ? r_cx : r_cx[7:0];
        3'b010: w_op1 = icache[0] ? r_dx : r_dx[7:0];
        3'b011: w_op1 = icache[0] ? r_bx : r_bx[7:0];
        3'b100: w_op1 = icache[0] ? r_sp : r_ax[15:8];
        3'b101: w_op1 = icache[0] ? r_bp : r_cx[15:8];
        3'b110: w_op1 = icache[0] ? r_si : r_dx[15:8];
        3'b111: w_op1 = icache[0] ? r_di : r_bx[15:8];
    
    endcase
    

    case (modrm_byte[5:3])
    
        3'b000: w_op2 = icache[0] ? r_ax : r_ax[7:0];
        3'b001: w_op2 = icache[0] ? r_cx : r_cx[7:0];
        3'b010: w_op2 = icache[0] ? r_dx : r_dx[7:0];
        3'b011: w_op2 = icache[0] ? r_bx : r_bx[7:0];
        3'b100: w_op2 = icache[0] ? r_sp : r_ax[15:8];
        3'b101: w_op2 = icache[0] ? r_bp : r_cx[15:8];
        3'b110: w_op2 = icache[0] ? r_si : r_dx[15:8];
        3'b111: w_op2 = icache[0] ? r_di : r_bx[15:8];
    
    endcase

end


always @* begin

    n_ip = r_ip + length;
        
end





always @(posedge clock) begin

    case (state)    
    



    
    `I_FETCH: begin
    

        if (instruction_done) begin
            
            segment_override     <= 1'b0;
            segment_override_num <= 2'b11;
            prefix_0F            <= 2'b0;
            operand_is_immediate <= 1'b0;
            immediate_size       <= 1'b0;
            alu_enable           <= 1'b0;
        
        end
        

        instruction_done <= 1'b0;
        



        if (current[0]) begin
        
            case (icp) 
            
                3'h0: begin icache[7:0]   <= i_data[15:8]; end
                3'h1: begin icache[15:8]  <= i_data[15:8]; end
                3'h2: begin icache[23:16] <= i_data[15:8]; end
                3'h3: begin icache[31:24] <= i_data[15:8]; end
                3'h4: begin icache[39:32] <= i_data[15:8]; end
                3'h5: begin icache[47:40] <= i_data[15:8]; state <= `I_DECODE; end
            
            endcase

            current <= current + 1'b1;
            icp     <= icp + 1'b1;
        
        end else begin
        
            case (icp)
            
                3'h0: begin icp <= 3'h2; icache[15:0]  <= i_data[15:0]; end
                3'h1: begin icp <= 3'h3; icache[23:8]  <= i_data[15:0]; end
                3'h2: begin icp <= 3'h4; icache[31:16] <= i_data[15:0]; end
                3'h3: begin icp <= 3'h5; icache[39:24] <= i_data[15:0]; end
                3'h4: begin icp <= 3'h0; icache[47:32] <= i_data[15:0]; state <= `I_DECODE; end
                3'h5: begin icp <= 3'h0; icache[47:40] <= i_data[ 7:0]; state <= `I_DECODE; end    
            
            endcase
                    
            current <= current + 2'h2;
            icp     <= icp + 2'h2;

        end
    
    end
    



    
    `I_DECODE: begin
    



        case (length)
        
            3'h1: begin icp <= 3'h5; icache[39:0] <= icache[47:8];  end
            3'h2: begin icp <= 3'h4; icache[31:0] <= icache[47:16]; end
            3'h3: begin icp <= 3'h3; icache[23:0] <= icache[47:24]; end
            3'h4: begin icp <= 3'h2; icache[15:0] <= icache[47:32]; end
            3'h5: begin icp <= 3'h1; icache[ 7:0] <= icache[47:40]; end
            3'h6: begin icp <= 3'h0; end

        endcase



        current <= (r_ip + 3'h6);
        r_ip    <= n_ip;
        


    



            

        



        if (has_prefixed) begin
        
            state <= `I_FETCH;
            casex (icache[7:0])
            
                8'b0000_1111: prefix_0F <= 1'b1;
            

                8'b001x_x110: begin segment_override <= 1'b1; segment_override_num <= {1'b0,icache[4:3]}; end
                

                8'b0110_010x: begin segment_override <= 1'b1; segment_override_num <= {1'b1,icache[1:0]}; end
                


            endcase        
        
        end    

        else if (has_modrm_byte) begin
        

            instruction_done <= 1'b1;



            _op1    <= w_op1;
            _op2    <= w_op2;
            target  <= icache[1];
            

            if (modrm_byte[7:6] != 2'b11) begin
            
                alt     <= 1'b1;
                wsize   <= icache[0];
                segment <= e_segment;
                address <= e_address;
                state   <= `I_READ_DATA;
            
            end else begin

                state  <= `I_EXECUTE;
                
            end
        
        end

        else begin

            state <= `I_EXECUTE;
            
        end

    end    






    `I_READ_DATA: begin
    

        if (wsize) begin

            if (address[0]) begin
            
                state   <= `I_READ_DATA_WIDE;            
                address <= address + 1'h1;             
                _op1    <= i_data[15:8];

            end else begin

                state   <= `I_EXECUTE;
                _op1    <= i_data[15:0];

            end        


        end else begin

            state <= `I_EXECUTE;
            _op1  <= address[0] ? i_data[15:8] : i_data[7:0];

        end

    end
    

    `I_READ_DATA_WIDE: begin 
    
        state       <= `I_EXECUTE;
        _op1[15:8]  <= i_data[7:0];
        address     <= address - 1'h1;

    end
    
    `I_EXECUTE: begin
    
        state <= `I_FETCH;
    
    end

    endcase
end

endmodule