data/full_repos/permissive/169382915/rtl/coprocessor/scarv_cop_top.v
1: b'%Error: data/full_repos/permissive/169382915/rtl/coprocessor/scarv_cop_top.v:64: Cannot find include file: scarv_cop_common.vh\n`include "scarv_cop_common.vh" \n         ^~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/169382915/rtl/coprocessor,data/full_repos/permissive/169382915/scarv_cop_common.vh\n             data/full_repos/permissive/169382915/rtl/coprocessor,data/full_repos/permissive/169382915/scarv_cop_common.vh.v\n             data/full_repos/permissive/169382915/rtl/coprocessor,data/full_repos/permissive/169382915/scarv_cop_common.vh.sv\n             scarv_cop_common.vh\n             scarv_cop_common.vh.v\n             scarv_cop_common.vh.sv\n             obj_dir/scarv_cop_common.vh\n             obj_dir/scarv_cop_common.vh.v\n             obj_dir/scarv_cop_common.vh.sv\n%Error: Exiting due to 1 error(s)\n'
module scarv_cop_top (




input  wire             g_clk           ,
output wire             g_clk_req       ,
input  wire             g_resetn        ,



`ifdef FORMAL
output wire [31:0]      cop_random      ,
output wire             cop_rand_sample ,

`VTX_REGISTER_PORTS_OUT(cprs_snoop)
`endif



input  wire             cpu_insn_req    ,
output                  cop_insn_ack    ,
input  wire [31:0]      cpu_insn_enc    ,
input  wire [31:0]      cpu_rs1         ,
input  wire [31:0]      cpu_rs2         ,

output                  cop_wen         ,
output      [ 4:0]      cop_waddr       ,
output      [31:0]      cop_wdata       ,
output      [ 2:0]      cop_result      ,
output                  cop_insn_rsp    ,
input  wire             cpu_insn_ack    ,



output wire             cop_mem_cen     ,
output wire             cop_mem_wen     ,
output wire [31:0]      cop_mem_addr    ,
output wire [31:0]      cop_mem_wdata   ,
input  wire [31:0]      cop_mem_rdata   ,
output wire [ 3:0]      cop_mem_ben     ,
input  wire             cop_mem_stall   ,
input  wire             cop_mem_error

);


`include "scarv_cop_common.vh"










parameter FAST_COP_CPU_IF = 0;





wire          id_exception    ;

wire [ 8:0]   id_class        ;
wire [15:0]   id_subclass     ;

wire          id_cprs_init    ;
wire          cprs_init_done  ;

wire [ 2:0]   id_pw           ;
wire [ 3:0]   id_crs1         ;
wire [ 3:0]   id_crs2         ;
wire [ 3:0]   id_crs3         ;
wire [ 3:0]   id_crd          ;
wire [ 3:0]   id_crd1         ;
wire [ 3:0]   id_crd2         ;
wire [ 4:0]   id_rd           ;
wire [ 4:0]   id_rs1          ;
wire [31:0]   id_imm          ;
wire          id_wb_h         ;
wire          id_wb_b         ;

wire          crs1_ren   = 1'b1   ;
wire [ 3:0]   crs1_addr  = malu_rdm_in_rs ? id_crd1 : id_crs1;

wire          crs2_ren   = 1'b1   ;
wire [ 3:0]   crs2_addr  = malu_rdm_in_rs ? id_crd2 : id_crs2;

wire          crs3_ren   = 1'b1   ;
wire [ 3:0]   crs3_addr  = malu_rdm_in_rs ? id_crs1 : id_crs3;

wire [31:0]   crs1_rdata      ;
wire [31:0]   crs2_rdata      ;
wire [31:0]   crs3_rdata      ;

wire [ 3:0]   crd_wen         ;
wire [ 3:0]   crd_addr        ;
wire [31:0]   crd_wdata       ;

wire          insn_valid;
wire          insn_finish;
wire          insn_accept;
wire          fu_done;

wire          palu_ivalid      ;
wire          palu_idone       ;
wire [ 3:0]   palu_cpr_rd_ben  ;
wire [31:0]   palu_cpr_rd_wdata;

wire          mem_ivalid       ;
wire          mem_idone        ;
wire          mem_is_store     ;
wire          mem_addr_error   ;
wire          mem_bus_error    ;
wire [ 3:0]   mem_cpr_rd_ben   ;
wire [31:0]   mem_cpr_rd_wdata ;

wire          malu_rdm_in_rs   ;
wire          malu_ivalid      ;
wire          malu_idone       ;
wire [ 3:0]   malu_cpr_rd_ben  ;
wire [31:0]   malu_cpr_rd_wdata;

wire          rng_ivalid       ;
wire          rng_idone        ;
wire [ 3:0]   rng_cpr_rd_ben   ;
wire [31:0]   rng_cpr_rd_wdata ;

wire          aes_ivalid       ;
wire          aes_idone        ;
wire [ 3:0]   aes_cpr_rd_ben   ;
wire [31:0]   aes_cpr_rd_wdata ;

wire          sha3_ivalid       ;
wire          sha3_idone        ;
wire [ 3:0]   sha3_cpr_rd_ben   ;
wire [31:0]   sha3_cpr_rd_wdata ;

wire          perm_ivalid      ;
wire          perm_idone       ;
wire [ 3:0]   perm_cpr_rd_ben  ;
wire [31:0]   perm_cpr_rd_wdata;







assign palu_ivalid = 
    insn_valid  && (
    id_class[SCARV_COP_ICLASS_PACKED_ARITH] ||
    id_class[SCARV_COP_ICLASS_MOVE        ] ||
    id_class[SCARV_COP_ICLASS_BITWISE     ] );

assign aes_ivalid   = insn_valid && id_class[SCARV_COP_ICLASS_AES];

assign sha3_ivalid  = insn_valid && id_class[SCARV_COP_ICLASS_SHA3];

assign malu_ivalid  = insn_valid && id_class[SCARV_COP_ICLASS_MP];

assign mem_ivalid   = insn_valid && id_class[SCARV_COP_ICLASS_LOADSTORE];

assign rng_ivalid   = insn_valid && id_class[SCARV_COP_ICLASS_RANDOM];

assign perm_ivalid  = insn_valid && id_class[SCARV_COP_ICLASS_PERMUTE];







assign crd_wen   = palu_cpr_rd_ben |
                   mem_cpr_rd_ben  |
                   malu_cpr_rd_ben |
                   rng_cpr_rd_ben  |
                   aes_cpr_rd_ben  |
                   perm_cpr_rd_ben ;

assign crd_addr  = !malu_ivalid ? id_crd :
                   !malu_idone  ? id_crd1:
                                  id_crd2;

assign crd_wdata = palu_cpr_rd_wdata |
                   mem_cpr_rd_wdata  |
                   malu_cpr_rd_wdata |
                   rng_cpr_rd_wdata  |
                   aes_cpr_rd_wdata  |
                   perm_cpr_rd_wdata ;








wire        n_cop_wen   ;
wire [ 4:0] n_cop_waddr ;
wire [31:0] n_cop_wdata ;
wire [ 2:0] n_cop_result;

assign n_cop_waddr = id_rd;

assign n_cop_wen   = 
    (id_class[SCARV_COP_ICLASS_MOVE]    &&
     id_subclass[SCARV_COP_SCLASS_XCR2GPR]   )  ||
    (id_class[SCARV_COP_ICLASS_SHA3  ]          )  ||
    (id_class[SCARV_COP_ICLASS_RANDOM]  &&
     id_subclass[SCARV_COP_SCLASS_RTEST]     )  ||
    (id_class[SCARV_COP_ICLASS_MP]      &&
     (id_subclass[SCARV_COP_SCLASS_MEQU] ||
      id_subclass[SCARV_COP_SCLASS_MLTE] ||
      id_subclass[SCARV_COP_SCLASS_MGTE] ) )   ;

assign n_cop_wdata = 
    id_class[SCARV_COP_ICLASS_MOVE  ] ? palu_cpr_rd_wdata : 
    id_class[SCARV_COP_ICLASS_SHA3  ] ? sha3_cpr_rd_wdata : 
    id_class[SCARV_COP_ICLASS_RANDOM] ? rng_cpr_rd_wdata  : 
                                        malu_cpr_rd_wdata ;




assign n_cop_result= 
    id_exception ?  SCARV_COP_INSN_BAD_INS : (
    {3{!mem_is_store & mem_addr_error}} & SCARV_COP_INSN_BAD_LAD |
    {3{!mem_is_store & mem_bus_error }} & SCARV_COP_INSN_LD_ERR  |
    {3{ mem_is_store & mem_addr_error}} & SCARV_COP_INSN_BAD_SAD |
    {3{ mem_is_store & mem_bus_error }} & SCARV_COP_INSN_ST_ERR  |
                                          SCARV_COP_INSN_SUCCESS );


wire [31:0] u_insn_enc;
wire [31:0] u_rs1;
wire [31:0] u_rs2;






generate if(FAST_COP_CPU_IF == 0) begin

    reg            r_cop_wen   ;
    reg [ 4:0]     r_cop_waddr ;
    reg [31:0]     r_cop_wdata ;
    reg [ 2:0]     r_cop_result;



    always @(posedge g_clk) if(!g_resetn) begin
        r_cop_wen    <= 1'b0;
        r_cop_waddr  <= 5'b0;
        r_cop_wdata  <= 32'b0;
        r_cop_result <= 3'b0;
    end else if(insn_finish) begin
        r_cop_wen    <= n_cop_wen   ;
        r_cop_waddr  <= n_cop_waddr ;
        r_cop_wdata  <= n_cop_wdata ;
        r_cop_result <= n_cop_result;
    end
    
    assign cop_wen    = r_cop_wen   ;
    assign cop_waddr  = r_cop_waddr ;
    assign cop_wdata  = r_cop_wdata ;
    assign cop_result = r_cop_result;



    reg  [31:0] r_insn_enc;
    reg  [31:0] r_rs1;
    reg  [31:0] r_rs2;

    assign u_insn_enc = (insn_accept) ? cpu_insn_enc : r_insn_enc;
    assign u_rs1      = (insn_accept) ? cpu_rs1      : r_rs1     ;
    assign u_rs2      = (insn_accept) ? cpu_rs2      : r_rs2     ;

    always @(posedge g_clk) if(!g_resetn) begin
            r_insn_enc <= 32'b0;
        end else if(cpu_insn_req && cop_insn_ack)
            r_insn_enc <= cpu_insn_enc;    

    always @(posedge g_clk) if(!g_resetn) begin
            r_rs1      <= 32'b0;
        end else if(cpu_insn_req && cop_insn_ack)
            r_rs1      <= cpu_rs1     ;    
    
    always @(posedge g_clk) if(!g_resetn) begin
            r_rs2      <= 32'b0;
        end else if(cpu_insn_req && cop_insn_ack)
            r_rs2      <= cpu_rs2     ;    

end else if(FAST_COP_CPU_IF == 1) begin
        
    assign cop_wen    = n_cop_wen   ;
    assign cop_waddr  = n_cop_waddr ;
    assign cop_wdata  = n_cop_wdata ;
    assign cop_result = n_cop_result;

    assign u_insn_enc = cpu_insn_enc;
    assign u_rs1      = cpu_rs1     ;
    assign u_rs2      = cpu_rs2     ;

end endgenerate




generate if(FAST_COP_CPU_IF == 0) begin

    assign  fu_done         = 
        mem_idone || palu_idone || malu_idone || 
        rng_idone || aes_idone  || sha3_idone ||
        cprs_init_done || perm_idone ||
        (id_exception && insn_accept);
    
    assign  insn_valid      = insn_accept ||
                              cop_fsm == FSM_EXECUTING;
    assign  insn_accept     = cpu_insn_req && cop_insn_ack;
    wire    insn_retired    = cop_insn_rsp && cpu_insn_ack;
    assign  insn_finish     = fu_done;
    
    localparam FSM_IDLE         = 0;
    localparam FSM_WAITING      = 1;
    localparam FSM_EXECUTING    = 2;
    localparam FSM_FINISHED     = 3;
    
    reg           n_cop_insn_ack;
    reg           n_cop_insn_rsp;
    
    reg     [2:0] cop_fsm;
    reg     [2:0] n_cop_fsm;
    
    always @(*) begin
        
        n_cop_fsm       = FSM_IDLE;
        n_cop_insn_ack  = 1'b0;
        n_cop_insn_rsp  = 1'b0;
        
        case(cop_fsm)
    
        FSM_IDLE     : begin
            n_cop_fsm       = FSM_WAITING;
            n_cop_insn_ack  = 1'b1;
        end
    
        FSM_WAITING  : begin
            n_cop_insn_ack = 1'b1;
            if(cpu_insn_req && n_cop_insn_ack) begin
                if(insn_finish) begin
                    n_cop_fsm   = FSM_FINISHED;
                    n_cop_insn_rsp = 1'b1;
                    n_cop_insn_ack = 1'b0;
                end else begin
                    n_cop_fsm   = FSM_EXECUTING;
                    n_cop_insn_ack = 1'b0;
                end
            end else begin
                n_cop_fsm       = FSM_WAITING;
            end
        end
        
        FSM_EXECUTING: begin
            if(insn_finish) begin
                n_cop_fsm       = FSM_FINISHED;
                n_cop_insn_rsp  = 1'b1;
            end else begin
                n_cop_fsm       = FSM_EXECUTING;
            end
        end
    
        FSM_FINISHED : begin
            if(insn_retired) begin
                n_cop_fsm       = FSM_WAITING;
                n_cop_insn_ack  = 1'b1;
            end else begin
                n_cop_fsm       = FSM_FINISHED;
                n_cop_insn_rsp  = 1'b1;
            end
        end
    
    endcase end

    reg r_cop_insn_ack;
    reg r_cop_insn_rsp;

    assign cop_insn_ack = r_cop_insn_ack;
    assign cop_insn_rsp = r_cop_insn_rsp;
    
    always @(posedge g_clk) r_cop_insn_ack <= g_resetn ? n_cop_insn_ack : 1'b0;
    always @(posedge g_clk) r_cop_insn_rsp <= g_resetn ? n_cop_insn_rsp : 1'b0;
    
    always @(posedge g_clk) if(!g_resetn) begin
        cop_fsm <= FSM_IDLE;
    end else begin
        cop_fsm <= n_cop_fsm;
    end

end else if(FAST_COP_CPU_IF == 1) begin

    assign  fu_done         = 
        mem_idone || palu_idone || malu_idone ||
        rng_idone || aes_idone  || sha3_idone ||
        id_exception || cprs_init_done || perm_idone;

    assign  insn_valid      = cpu_insn_req;

    assign  cop_insn_rsp    = insn_valid && fu_done;
    assign  cop_insn_ack    = cop_insn_rsp;

end endgenerate
















scarv_cop_idecode i_scarv_cop_idecode (
.id_encoded  (u_insn_enc  ),
.id_exception(id_exception),
.id_class    (id_class    ),
.id_subclass (id_subclass ),
.id_pw       (id_pw       ),
.id_cprs_init(id_cprs_init),
.id_crs1     (id_crs1     ),
.id_crs2     (id_crs2     ),
.id_crs3     (id_crs3     ),
.id_crd      (id_crd      ),
.id_crd1     (id_crd1     ),
.id_crd2     (id_crd2     ),
.id_rd       (id_rd       ),
.id_rs1      (id_rs1      ),
.id_imm      (id_imm      ),
.id_wb_h     (id_wb_h     ),
.id_wb_b     (id_wb_b     )
);







scarv_cop_cprs i_scarv_cop_cprs(
.g_clk     (g_clk     ),
.g_clk_req (g_clk_req ),
.g_resetn  (g_resetn  ),
`ifdef FORMAL
`VTX_REGISTER_PORTS_RAISE(cprs_snoop)
`endif
.cprs_init (id_cprs_init),
.cprs_init_done (cprs_init_done),
.crs1_ren  (crs1_ren  ),
.crs1_addr (crs1_addr ),
.crs1_rdata(crs1_rdata),
.crs2_ren  (crs2_ren  ),
.crs2_addr (crs2_addr ),
.crs2_rdata(crs2_rdata),
.crs3_ren  (crs3_ren  ),
.crs3_addr (crs3_addr ),
.crs3_rdata(crs3_rdata),
.crd_wen   (crd_wen   ),
.crd_addr  (crd_addr  ),
.crd_wdata (crd_wdata )
);










scarv_cop_palu i_scarv_cop_palu (
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.palu_ivalid      (palu_ivalid      ),
.palu_idone       (palu_idone       ),
.gpr_rs1          (u_rs1            ),
.palu_rs1         (crs1_rdata       ),
.palu_rs2         (crs2_rdata       ),
.palu_rs3         (crs3_rdata       ),
.id_imm           (id_imm           ),
.id_pw            (id_pw            ),
.id_class         (id_class         ),
.id_subclass      (id_subclass      ),
.palu_cpr_rd_ben  (palu_cpr_rd_ben  ),
.palu_cpr_rd_wdata(palu_cpr_rd_wdata)
);








scarv_cop_aes i_scarv_cop_aes(
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.aes_ivalid       (aes_ivalid      ),
.aes_idone        (aes_idone       ),
.aes_rs1          (crs1_rdata      ),
.aes_rs2          (crs2_rdata      ),
.id_subclass      (id_subclass     ),
.aes_cpr_rd_ben   (aes_cpr_rd_ben  ),
.aes_cpr_rd_wdata (aes_cpr_rd_wdata)
);







scarv_cop_sha3 i_scarv_cop_sha3 (
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.sha3_ivalid      (sha3_ivalid     ),
.sha3_idone       (sha3_idone      ),
.sha3_rs1         (u_rs1           ),
.sha3_rs2         (u_rs2           ),
.id_subclass      (id_subclass     ),
.id_imm           (id_imm           ),
.sha3_cpr_rd_ben  (sha3_cpr_rd_ben  ),
.sha3_cpr_rd_wdata(sha3_cpr_rd_wdata)
);






scarv_cop_mem i_scarv_cop_mem (
.g_clk           (g_clk           ),
.g_resetn        (g_resetn        ),
.mem_ivalid      (mem_ivalid      ),
.mem_idone       (mem_idone       ),
.mem_is_store    (mem_is_store    ),
.mem_addr_error  (mem_addr_error  ),
.mem_bus_error   (mem_bus_error   ),
.gpr_rs1         (u_rs1           ),
.gpr_rs2         (u_rs2           ),
.cpr_rs1         (crs1_rdata      ),
.cpr_rs2         (crs2_rdata      ),
.cpr_rs3         (crs3_rdata      ),
.id_wb_h         (id_wb_h         ),
.id_wb_b         (id_wb_b         ),
.id_imm          (id_imm          ),
.id_subclass     (id_subclass     ),
.mem_cpr_rd_ben  (mem_cpr_rd_ben  ),
.mem_cpr_rd_wdata(mem_cpr_rd_wdata),
.cop_mem_cen     (cop_mem_cen     ),
.cop_mem_wen     (cop_mem_wen     ),
.cop_mem_addr    (cop_mem_addr    ),
.cop_mem_wdata   (cop_mem_wdata   ),
.cop_mem_rdata   (cop_mem_rdata   ),
.cop_mem_ben     (cop_mem_ben     ),
.cop_mem_stall   (cop_mem_stall   ),
.cop_mem_error   (cop_mem_error   )
);







scarv_cop_malu i_scarv_cop_malu (
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.malu_ivalid      (malu_ivalid      ),
.malu_idone       (malu_idone       ),
.malu_rdm_in_rs   (malu_rdm_in_rs   ),
.gpr_rs1          (u_rs1            ),
.malu_rs1         (crs1_rdata       ),
.malu_rs2         (crs2_rdata       ),
.malu_rs3         (crs3_rdata       ),
.id_imm           (id_imm           ),
.id_subclass      (id_subclass      ),
.malu_cpr_rd_ben  (malu_cpr_rd_ben  ),
.malu_cpr_rd_wdata(malu_cpr_rd_wdata)
);







scarv_cop_permute i_scarv_cop_permute (
.perm_ivalid      (perm_ivalid      ),
.perm_idone       (perm_idone       ),
.perm_rs1         (crs1_rdata       ),
.perm_rs3         (crs3_rdata       ),
.id_imm           (id_imm           ),
.id_subclass      (id_subclass      ),
.perm_cpr_rd_ben  (perm_cpr_rd_ben  ),
.perm_cpr_rd_wdata(perm_cpr_rd_wdata)
);





scarv_cop_rng i_scarv_cop_rng(
.g_clk           (g_clk           ),
.g_resetn        (g_resetn        ),
.rng_ivalid      (rng_ivalid      ),
.rng_idone       (rng_idone       ),
`ifdef FORMAL
.cop_random      (cop_random      ),
.cop_rand_sample (cop_rand_sample ),
`endif
.rng_rs1         (crs1_rdata      ),
.id_imm          (id_imm          ),
.id_subclass     (id_subclass     ),
.rng_cpr_rd_ben  (rng_cpr_rd_ben  ),
.rng_cpr_rd_wdata(rng_cpr_rd_wdata)
);

endmodule
module scarv_cop_top (




input  wire             g_clk           ,
output wire             g_clk_req       ,
input  wire             g_resetn        ,



`ifdef FORMAL
output wire [31:0]      cop_random      ,
output wire             cop_rand_sample ,

`VTX_REGISTER_PORTS_OUT(cprs_snoop)
`endif



input  wire             cpu_insn_req    ,
output                  cop_insn_ack    ,
input  wire [31:0]      cpu_insn_enc    ,
input  wire [31:0]      cpu_rs1         ,
input  wire [31:0]      cpu_rs2         ,

output                  cop_wen         ,
output      [ 4:0]      cop_waddr       ,
output      [31:0]      cop_wdata       ,
output      [ 2:0]      cop_result      ,
output                  cop_insn_rsp    ,
input  wire             cpu_insn_ack    ,



output wire             cop_mem_cen     ,
output wire             cop_mem_wen     ,
output wire [31:0]      cop_mem_addr    ,
output wire [31:0]      cop_mem_wdata   ,
input  wire [31:0]      cop_mem_rdata   ,
output wire [ 3:0]      cop_mem_ben     ,
input  wire             cop_mem_stall   ,
input  wire             cop_mem_error

);



`include "scarv_cop_common.vh"










parameter FAST_COP_CPU_IF = 0;





wire          id_exception    ;

wire [ 8:0]   id_class        ;
wire [15:0]   id_subclass     ;

wire          id_cprs_init    ;
wire          cprs_init_done  ;

wire [ 2:0]   id_pw           ;
wire [ 3:0]   id_crs1         ;
wire [ 3:0]   id_crs2         ;
wire [ 3:0]   id_crs3         ;
wire [ 3:0]   id_crd          ;
wire [ 3:0]   id_crd1         ;
wire [ 3:0]   id_crd2         ;
wire [ 4:0]   id_rd           ;
wire [ 4:0]   id_rs1          ;
wire [31:0]   id_imm          ;
wire          id_wb_h         ;
wire          id_wb_b         ;

wire          crs1_ren   = 1'b1   ;
wire [ 3:0]   crs1_addr  = malu_rdm_in_rs ? id_crd1 : id_crs1;

wire          crs2_ren   = 1'b1   ;
wire [ 3:0]   crs2_addr  = malu_rdm_in_rs ? id_crd2 : id_crs2;

wire          crs3_ren   = 1'b1   ;
wire [ 3:0]   crs3_addr  = malu_rdm_in_rs ? id_crs1 : id_crs3;

wire [31:0]   crs1_rdata      ;
wire [31:0]   crs2_rdata      ;
wire [31:0]   crs3_rdata      ;

wire [ 3:0]   crd_wen         ;
wire [ 3:0]   crd_addr        ;
wire [31:0]   crd_wdata       ;

wire          insn_valid;
wire          insn_finish;
wire          insn_accept;
wire          fu_done;

wire          palu_ivalid      ;
wire          palu_idone       ;
wire [ 3:0]   palu_cpr_rd_ben  ;
wire [31:0]   palu_cpr_rd_wdata;

wire          mem_ivalid       ;
wire          mem_idone        ;
wire          mem_is_store     ;
wire          mem_addr_error   ;
wire          mem_bus_error    ;
wire [ 3:0]   mem_cpr_rd_ben   ;
wire [31:0]   mem_cpr_rd_wdata ;

wire          malu_rdm_in_rs   ;
wire          malu_ivalid      ;
wire          malu_idone       ;
wire [ 3:0]   malu_cpr_rd_ben  ;
wire [31:0]   malu_cpr_rd_wdata;

wire          rng_ivalid       ;
wire          rng_idone        ;
wire [ 3:0]   rng_cpr_rd_ben   ;
wire [31:0]   rng_cpr_rd_wdata ;

wire          aes_ivalid       ;
wire          aes_idone        ;
wire [ 3:0]   aes_cpr_rd_ben   ;
wire [31:0]   aes_cpr_rd_wdata ;

wire          sha3_ivalid       ;
wire          sha3_idone        ;
wire [ 3:0]   sha3_cpr_rd_ben   ;
wire [31:0]   sha3_cpr_rd_wdata ;

wire          perm_ivalid      ;
wire          perm_idone       ;
wire [ 3:0]   perm_cpr_rd_ben  ;
wire [31:0]   perm_cpr_rd_wdata;







assign palu_ivalid = 
    insn_valid  && (
    id_class[SCARV_COP_ICLASS_PACKED_ARITH] ||
    id_class[SCARV_COP_ICLASS_MOVE        ] ||
    id_class[SCARV_COP_ICLASS_BITWISE     ] );

assign aes_ivalid   = insn_valid && id_class[SCARV_COP_ICLASS_AES];

assign sha3_ivalid  = insn_valid && id_class[SCARV_COP_ICLASS_SHA3];

assign malu_ivalid  = insn_valid && id_class[SCARV_COP_ICLASS_MP];

assign mem_ivalid   = insn_valid && id_class[SCARV_COP_ICLASS_LOADSTORE];

assign rng_ivalid   = insn_valid && id_class[SCARV_COP_ICLASS_RANDOM];

assign perm_ivalid  = insn_valid && id_class[SCARV_COP_ICLASS_PERMUTE];







assign crd_wen   = palu_cpr_rd_ben |
                   mem_cpr_rd_ben  |
                   malu_cpr_rd_ben |
                   rng_cpr_rd_ben  |
                   aes_cpr_rd_ben  |
                   perm_cpr_rd_ben ;

assign crd_addr  = !malu_ivalid ? id_crd :
                   !malu_idone  ? id_crd1:
                                  id_crd2;

assign crd_wdata = palu_cpr_rd_wdata |
                   mem_cpr_rd_wdata  |
                   malu_cpr_rd_wdata |
                   rng_cpr_rd_wdata  |
                   aes_cpr_rd_wdata  |
                   perm_cpr_rd_wdata ;








wire        n_cop_wen   ;
wire [ 4:0] n_cop_waddr ;
wire [31:0] n_cop_wdata ;
wire [ 2:0] n_cop_result;

assign n_cop_waddr = id_rd;

assign n_cop_wen   = 
    (id_class[SCARV_COP_ICLASS_MOVE]    &&
     id_subclass[SCARV_COP_SCLASS_XCR2GPR]   )  ||
    (id_class[SCARV_COP_ICLASS_SHA3  ]          )  ||
    (id_class[SCARV_COP_ICLASS_RANDOM]  &&
     id_subclass[SCARV_COP_SCLASS_RTEST]     )  ||
    (id_class[SCARV_COP_ICLASS_MP]      &&
     (id_subclass[SCARV_COP_SCLASS_MEQU] ||
      id_subclass[SCARV_COP_SCLASS_MLTE] ||
      id_subclass[SCARV_COP_SCLASS_MGTE] ) )   ;

assign n_cop_wdata = 
    id_class[SCARV_COP_ICLASS_MOVE  ] ? palu_cpr_rd_wdata : 
    id_class[SCARV_COP_ICLASS_SHA3  ] ? sha3_cpr_rd_wdata : 
    id_class[SCARV_COP_ICLASS_RANDOM] ? rng_cpr_rd_wdata  : 
                                        malu_cpr_rd_wdata ;




assign n_cop_result= 
    id_exception ?  SCARV_COP_INSN_BAD_INS : (
    {3{!mem_is_store & mem_addr_error}} & SCARV_COP_INSN_BAD_LAD |
    {3{!mem_is_store & mem_bus_error }} & SCARV_COP_INSN_LD_ERR  |
    {3{ mem_is_store & mem_addr_error}} & SCARV_COP_INSN_BAD_SAD |
    {3{ mem_is_store & mem_bus_error }} & SCARV_COP_INSN_ST_ERR  |
                                          SCARV_COP_INSN_SUCCESS );


wire [31:0] u_insn_enc;
wire [31:0] u_rs1;
wire [31:0] u_rs2;






generate if(FAST_COP_CPU_IF == 0) begin

    reg            r_cop_wen   ;
    reg [ 4:0]     r_cop_waddr ;
    reg [31:0]     r_cop_wdata ;
    reg [ 2:0]     r_cop_result;



    always @(posedge g_clk) if(!g_resetn) begin
        r_cop_wen    <= 1'b0;
        r_cop_waddr  <= 5'b0;
        r_cop_wdata  <= 32'b0;
        r_cop_result <= 3'b0;
    end else if(insn_finish) begin
        r_cop_wen    <= n_cop_wen   ;
        r_cop_waddr  <= n_cop_waddr ;
        r_cop_wdata  <= n_cop_wdata ;
        r_cop_result <= n_cop_result;
    end
    
    assign cop_wen    = r_cop_wen   ;
    assign cop_waddr  = r_cop_waddr ;
    assign cop_wdata  = r_cop_wdata ;
    assign cop_result = r_cop_result;



    reg  [31:0] r_insn_enc;
    reg  [31:0] r_rs1;
    reg  [31:0] r_rs2;

    assign u_insn_enc = (insn_accept) ? cpu_insn_enc : r_insn_enc;
    assign u_rs1      = (insn_accept) ? cpu_rs1      : r_rs1     ;
    assign u_rs2      = (insn_accept) ? cpu_rs2      : r_rs2     ;

    always @(posedge g_clk) if(!g_resetn) begin
            r_insn_enc <= 32'b0;
        end else if(cpu_insn_req && cop_insn_ack)
            r_insn_enc <= cpu_insn_enc;    

    always @(posedge g_clk) if(!g_resetn) begin
            r_rs1      <= 32'b0;
        end else if(cpu_insn_req && cop_insn_ack)
            r_rs1      <= cpu_rs1     ;    
    
    always @(posedge g_clk) if(!g_resetn) begin
            r_rs2      <= 32'b0;
        end else if(cpu_insn_req && cop_insn_ack)
            r_rs2      <= cpu_rs2     ;    

end else if(FAST_COP_CPU_IF == 1) begin
        
    assign cop_wen    = n_cop_wen   ;
    assign cop_waddr  = n_cop_waddr ;
    assign cop_wdata  = n_cop_wdata ;
    assign cop_result = n_cop_result;

    assign u_insn_enc = cpu_insn_enc;
    assign u_rs1      = cpu_rs1     ;
    assign u_rs2      = cpu_rs2     ;

end endgenerate




generate if(FAST_COP_CPU_IF == 0) begin

    assign  fu_done         = 
        mem_idone || palu_idone || malu_idone || 
        rng_idone || aes_idone  || sha3_idone ||
        cprs_init_done || perm_idone ||
        (id_exception && insn_accept);
    
    assign  insn_valid      = insn_accept ||
                              cop_fsm == FSM_EXECUTING;
    assign  insn_accept     = cpu_insn_req && cop_insn_ack;
    wire    insn_retired    = cop_insn_rsp && cpu_insn_ack;
    assign  insn_finish     = fu_done;
    
    localparam FSM_IDLE         = 0;
    localparam FSM_WAITING      = 1;
    localparam FSM_EXECUTING    = 2;
    localparam FSM_FINISHED     = 3;
    
    reg           n_cop_insn_ack;
    reg           n_cop_insn_rsp;
    
    reg     [2:0] cop_fsm;
    reg     [2:0] n_cop_fsm;
    
    always @(*) begin
        
        n_cop_fsm       = FSM_IDLE;
        n_cop_insn_ack  = 1'b0;
        n_cop_insn_rsp  = 1'b0;
        
        case(cop_fsm)
    
        FSM_IDLE     : begin
            n_cop_fsm       = FSM_WAITING;
            n_cop_insn_ack  = 1'b1;
        end
    
        FSM_WAITING  : begin
            n_cop_insn_ack = 1'b1;
            if(cpu_insn_req && n_cop_insn_ack) begin
                if(insn_finish) begin
                    n_cop_fsm   = FSM_FINISHED;
                    n_cop_insn_rsp = 1'b1;
                    n_cop_insn_ack = 1'b0;
                end else begin
                    n_cop_fsm   = FSM_EXECUTING;
                    n_cop_insn_ack = 1'b0;
                end
            end else begin
                n_cop_fsm       = FSM_WAITING;
            end
        end
        
        FSM_EXECUTING: begin
            if(insn_finish) begin
                n_cop_fsm       = FSM_FINISHED;
                n_cop_insn_rsp  = 1'b1;
            end else begin
                n_cop_fsm       = FSM_EXECUTING;
            end
        end
    
        FSM_FINISHED : begin
            if(insn_retired) begin
                n_cop_fsm       = FSM_WAITING;
                n_cop_insn_ack  = 1'b1;
            end else begin
                n_cop_fsm       = FSM_FINISHED;
                n_cop_insn_rsp  = 1'b1;
            end
        end
    
    endcase end

    reg r_cop_insn_ack;
    reg r_cop_insn_rsp;

    assign cop_insn_ack = r_cop_insn_ack;
    assign cop_insn_rsp = r_cop_insn_rsp;
    
    always @(posedge g_clk) r_cop_insn_ack <= g_resetn ? n_cop_insn_ack : 1'b0;
    always @(posedge g_clk) r_cop_insn_rsp <= g_resetn ? n_cop_insn_rsp : 1'b0;
    
    always @(posedge g_clk) if(!g_resetn) begin
        cop_fsm <= FSM_IDLE;
    end else begin
        cop_fsm <= n_cop_fsm;
    end

end else if(FAST_COP_CPU_IF == 1) begin

    assign  fu_done         = 
        mem_idone || palu_idone || malu_idone ||
        rng_idone || aes_idone  || sha3_idone ||
        id_exception || cprs_init_done || perm_idone;

    assign  insn_valid      = cpu_insn_req;

    assign  cop_insn_rsp    = insn_valid && fu_done;
    assign  cop_insn_ack    = cop_insn_rsp;

end endgenerate
















scarv_cop_idecode i_scarv_cop_idecode (
.id_encoded  (u_insn_enc  ),
.id_exception(id_exception),
.id_class    (id_class    ),
.id_subclass (id_subclass ),
.id_pw       (id_pw       ),
.id_cprs_init(id_cprs_init),
.id_crs1     (id_crs1     ),
.id_crs2     (id_crs2     ),
.id_crs3     (id_crs3     ),
.id_crd      (id_crd      ),
.id_crd1     (id_crd1     ),
.id_crd2     (id_crd2     ),
.id_rd       (id_rd       ),
.id_rs1      (id_rs1      ),
.id_imm      (id_imm      ),
.id_wb_h     (id_wb_h     ),
.id_wb_b     (id_wb_b     )
);







scarv_cop_cprs i_scarv_cop_cprs(
.g_clk     (g_clk     ),
.g_clk_req (g_clk_req ),
.g_resetn  (g_resetn  ),
`ifdef FORMAL
`VTX_REGISTER_PORTS_RAISE(cprs_snoop)
`endif
.cprs_init (id_cprs_init),
.cprs_init_done (cprs_init_done),
.crs1_ren  (crs1_ren  ),
.crs1_addr (crs1_addr ),
.crs1_rdata(crs1_rdata),
.crs2_ren  (crs2_ren  ),
.crs2_addr (crs2_addr ),
.crs2_rdata(crs2_rdata),
.crs3_ren  (crs3_ren  ),
.crs3_addr (crs3_addr ),
.crs3_rdata(crs3_rdata),
.crd_wen   (crd_wen   ),
.crd_addr  (crd_addr  ),
.crd_wdata (crd_wdata )
);










scarv_cop_palu i_scarv_cop_palu (
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.palu_ivalid      (palu_ivalid      ),
.palu_idone       (palu_idone       ),
.gpr_rs1          (u_rs1            ),
.palu_rs1         (crs1_rdata       ),
.palu_rs2         (crs2_rdata       ),
.palu_rs3         (crs3_rdata       ),
.id_imm           (id_imm           ),
.id_pw            (id_pw            ),
.id_class         (id_class         ),
.id_subclass      (id_subclass      ),
.palu_cpr_rd_ben  (palu_cpr_rd_ben  ),
.palu_cpr_rd_wdata(palu_cpr_rd_wdata)
);








scarv_cop_aes i_scarv_cop_aes(
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.aes_ivalid       (aes_ivalid      ),
.aes_idone        (aes_idone       ),
.aes_rs1          (crs1_rdata      ),
.aes_rs2          (crs2_rdata      ),
.id_subclass      (id_subclass     ),
.aes_cpr_rd_ben   (aes_cpr_rd_ben  ),
.aes_cpr_rd_wdata (aes_cpr_rd_wdata)
);







scarv_cop_sha3 i_scarv_cop_sha3 (
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.sha3_ivalid      (sha3_ivalid     ),
.sha3_idone       (sha3_idone      ),
.sha3_rs1         (u_rs1           ),
.sha3_rs2         (u_rs2           ),
.id_subclass      (id_subclass     ),
.id_imm           (id_imm           ),
.sha3_cpr_rd_ben  (sha3_cpr_rd_ben  ),
.sha3_cpr_rd_wdata(sha3_cpr_rd_wdata)
);






scarv_cop_mem i_scarv_cop_mem (
.g_clk           (g_clk           ),
.g_resetn        (g_resetn        ),
.mem_ivalid      (mem_ivalid      ),
.mem_idone       (mem_idone       ),
.mem_is_store    (mem_is_store    ),
.mem_addr_error  (mem_addr_error  ),
.mem_bus_error   (mem_bus_error   ),
.gpr_rs1         (u_rs1           ),
.gpr_rs2         (u_rs2           ),
.cpr_rs1         (crs1_rdata      ),
.cpr_rs2         (crs2_rdata      ),
.cpr_rs3         (crs3_rdata      ),
.id_wb_h         (id_wb_h         ),
.id_wb_b         (id_wb_b         ),
.id_imm          (id_imm          ),
.id_subclass     (id_subclass     ),
.mem_cpr_rd_ben  (mem_cpr_rd_ben  ),
.mem_cpr_rd_wdata(mem_cpr_rd_wdata),
.cop_mem_cen     (cop_mem_cen     ),
.cop_mem_wen     (cop_mem_wen     ),
.cop_mem_addr    (cop_mem_addr    ),
.cop_mem_wdata   (cop_mem_wdata   ),
.cop_mem_rdata   (cop_mem_rdata   ),
.cop_mem_ben     (cop_mem_ben     ),
.cop_mem_stall   (cop_mem_stall   ),
.cop_mem_error   (cop_mem_error   )
);







scarv_cop_malu i_scarv_cop_malu (
.g_clk            (g_clk           ),
.g_resetn         (g_resetn        ),
.malu_ivalid      (malu_ivalid      ),
.malu_idone       (malu_idone       ),
.malu_rdm_in_rs   (malu_rdm_in_rs   ),
.gpr_rs1          (u_rs1            ),
.malu_rs1         (crs1_rdata       ),
.malu_rs2         (crs2_rdata       ),
.malu_rs3         (crs3_rdata       ),
.id_imm           (id_imm           ),
.id_subclass      (id_subclass      ),
.malu_cpr_rd_ben  (malu_cpr_rd_ben  ),
.malu_cpr_rd_wdata(malu_cpr_rd_wdata)
);







scarv_cop_permute i_scarv_cop_permute (
.perm_ivalid      (perm_ivalid      ),
.perm_idone       (perm_idone       ),
.perm_rs1         (crs1_rdata       ),
.perm_rs3         (crs3_rdata       ),
.id_imm           (id_imm           ),
.id_subclass      (id_subclass      ),
.perm_cpr_rd_ben  (perm_cpr_rd_ben  ),
.perm_cpr_rd_wdata(perm_cpr_rd_wdata)
);





scarv_cop_rng i_scarv_cop_rng(
.g_clk           (g_clk           ),
.g_resetn        (g_resetn        ),
.rng_ivalid      (rng_ivalid      ),
.rng_idone       (rng_idone       ),
`ifdef FORMAL
.cop_random      (cop_random      ),
.cop_rand_sample (cop_rand_sample ),
`endif
.rng_rs1         (crs1_rdata      ),
.id_imm          (id_imm          ),
.id_subclass     (id_subclass     ),
.rng_cpr_rd_ben  (rng_cpr_rd_ben  ),
.rng_cpr_rd_wdata(rng_cpr_rd_wdata)
);

endmodule