../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: