../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_dummy_instr.sv Cov: 87.3%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: 
   5: /**
   6:  * Dummy instruction module
   7:  *
   8:  * Provides pseudo-randomly inserted fake instructions for secure code obfuscation
   9:  */
  10: 
  11: module ibex_dummy_instr (
  12:     // Clock and reset
  13:     input  logic        clk_i,
  14:     input  logic        rst_ni,
  15: 
  16:     // Interface to CSRs
  17:     input  logic        dummy_instr_en_i,
  18:     input  logic [2:0]  dummy_instr_mask_i,
  19:     input  logic        dummy_instr_seed_en_i,
  20:     input  logic [31:0] dummy_instr_seed_i,
  21: 
  22:     // Interface to IF stage
  23:     input  logic        fetch_valid_i,
  24:     input  logic        id_in_ready_i,
  25:     output logic        insert_dummy_instr_o,
  26:     output logic [31:0] dummy_instr_data_o
  27: );
  28: 
  29:   localparam int unsigned TIMEOUT_CNT_W = 5;
  30:   localparam int unsigned OP_W          = 5;
  31: 
  32:   typedef enum logic [1:0] {
  33:     DUMMY_ADD = 2'b00,
  34:     DUMMY_MUL = 2'b01,
  35:     DUMMY_DIV = 2'b10,
  36:     DUMMY_AND = 2'b11
  37:   } dummy_instr_e;
  38: 
  39:   typedef struct packed {
  40:     dummy_instr_e             instr_type;
  41:     logic [OP_W-1:0]          op_b;
  42:     logic [OP_W-1:0]          op_a;
  43:     logic [TIMEOUT_CNT_W-1:0] cnt;
  44:   } lfsr_data_t;
  45:   localparam int unsigned LFSR_OUT_W = $bits(lfsr_data_t);
  46: 
  47:   lfsr_data_t               lfsr_data;
  48:   logic [TIMEOUT_CNT_W-1:0] dummy_cnt_incr, dummy_cnt_threshold;
  49:   logic [TIMEOUT_CNT_W-1:0] dummy_cnt_d, dummy_cnt_q;
  50:   logic                     dummy_cnt_en;
  51:   logic                     lfsr_en;
  52:   logic [LFSR_OUT_W-1:0]    lfsr_state;
  53:   logic                     insert_dummy_instr;
  54:   logic [6:0]               dummy_set;
  55:   logic [2:0]               dummy_opcode;
  56:   logic [31:0]              dummy_instr;
  57: 
  58:   // Shift the LFSR every time we insert an instruction
  59:   assign lfsr_en = insert_dummy_instr & id_in_ready_i;
  60: 
  61:   prim_lfsr #(
  62:       .LfsrDw      ( 32         ),
  63:       .StateOutDw  ( LFSR_OUT_W )
  64:   ) lfsr_i (
  65:       .clk_i     ( clk_i                 ),
  66:       .rst_ni    ( rst_ni                ),
  67:       .seed_en_i ( dummy_instr_seed_en_i ),
  68:       .seed_i    ( dummy_instr_seed_i    ),
  69:       .lfsr_en_i ( lfsr_en               ),
  70:       .entropy_i ( '0                    ),
  71:       .state_o   ( lfsr_state            )
  72:   );
  73: 
  74:   // Extract fields from LFSR
  75:   assign lfsr_data = lfsr_data_t'(lfsr_state);
  76: 
  77:   // Set count threshold for inserting a new instruction. This is the pseudo-random value from the
  78:   // LFSR with a mask applied (based on CSR config data) to shorten the period if required.
  79:   assign dummy_cnt_threshold = lfsr_data.cnt & {dummy_instr_mask_i,{TIMEOUT_CNT_W-3{1'b1}}};
  80:   assign dummy_cnt_incr      = dummy_cnt_q + {{TIMEOUT_CNT_W-1{1'b0}},1'b1};
  81:   // Clear the counter everytime a new instruction is inserted
  82:   assign dummy_cnt_d         = insert_dummy_instr ? '0 : dummy_cnt_incr;
  83:   // Increment the counter for each executed instruction while dummy instuctions are
  84:   // enabled.
  85:   assign dummy_cnt_en        = dummy_instr_en_i & id_in_ready_i &
  86:                                (fetch_valid_i | insert_dummy_instr);
  87: 
  88:   always_ff @(posedge clk_i or negedge rst_ni) begin
  89:     if (!rst_ni) begin
  90:       dummy_cnt_q <= '0;
  91:     end else if (dummy_cnt_en) begin
  92:       dummy_cnt_q <= dummy_cnt_d;
  93:     end
  94:   end
  95: 
  96:   // Insert a dummy instruction each time the counter hits the threshold
  97:   assign insert_dummy_instr = dummy_instr_en_i & (dummy_cnt_q == dummy_cnt_threshold);
  98: 
  99:   // Encode instruction
 100:   always_comb begin
 101:     unique case (lfsr_data.instr_type)
 102:       DUMMY_ADD : begin
 103:         dummy_set    = 7'b0000000;
 104:         dummy_opcode = 3'b000;
 105:       end
 106:       DUMMY_MUL : begin
 107:         dummy_set    = 7'b0000001;
 108:         dummy_opcode = 3'b000;
 109:       end
 110:       DUMMY_DIV : begin
 111:         dummy_set    = 7'b0000001;
 112:         dummy_opcode = 3'b100;
 113:       end
 114:       DUMMY_AND : begin
 115:         dummy_set    = 7'b0000000;
 116:         dummy_opcode = 3'b111;
 117:       end
 118:       default : begin
 119:         dummy_set    = 7'b0000000;
 120:         dummy_opcode = 3'b000;
 121:       end
 122:     endcase
 123:   end
 124: 
 125:   //                    SET       RS2            RS1            OP           RD
 126:   assign dummy_instr = {dummy_set,lfsr_data.op_b,lfsr_data.op_a,dummy_opcode,5'h00,7'h33};
 127: 
 128:   // Assign outputs
 129:   assign insert_dummy_instr_o = insert_dummy_instr;
 130:   assign dummy_instr_data_o   = dummy_instr;
 131: 
 132: endmodule
 133: