1 //////////////////////////////////////////////////////////////////////
3 //// OR1200's Instruction decode ////
5 //// This file is part of the OpenRISC 1200 project ////
6 //// http://www.opencores.org/cores/or1k/ ////
9 //// Majority of instruction decoding is performed here. ////
12 //// - make it smaller and faster ////
15 //// - Damjan Lampret, lampret@opencores.org ////
17 //////////////////////////////////////////////////////////////////////
19 //// Copyright (C) 2000 Authors and OPENCORES.ORG ////
21 //// This source file may be used and distributed without ////
22 //// restriction provided that this copyright statement is not ////
23 //// removed from the file and that any derivative work contains ////
24 //// the original copyright notice and the associated disclaimer. ////
26 //// This source file is free software; you can redistribute it ////
27 //// and/or modify it under the terms of the GNU Lesser General ////
28 //// Public License as published by the Free Software Foundation; ////
29 //// either version 2.1 of the License, or (at your option) any ////
30 //// later version. ////
32 //// This source is distributed in the hope that it will be ////
33 //// useful, but WITHOUT ANY WARRANTY; without even the implied ////
34 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
35 //// PURPOSE. See the GNU Lesser General Public License for more ////
38 //// You should have received a copy of the GNU Lesser General ////
39 //// Public License along with this source; if not, download it ////
40 //// from http://www.opencores.org/lgpl.shtml ////
42 //////////////////////////////////////////////////////////////////////
44 // CVS Revision History
47 // Revision 1.6 2002/03/29 15:16:54 lampret
48 // Some of the warnings fixed.
50 // Revision 1.5 2002/02/01 19:56:54 lampret
51 // Fixed combinational loops.
53 // Revision 1.4 2002/01/28 01:15:59 lampret
54 // Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
56 // Revision 1.3 2002/01/18 14:21:43 lampret
57 // Fixed 'the NPC single-step fix'.
59 // Revision 1.2 2002/01/14 06:18:22 lampret
60 // Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
62 // Revision 1.1 2002/01/03 08:16:15 lampret
63 // New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
65 // Revision 1.14 2001/11/30 18:59:17 simons
66 // force_dslot_fetch does not work - allways zero.
68 // Revision 1.13 2001/11/20 18:46:15 simons
69 // Break point bug fixed
71 // Revision 1.12 2001/11/18 08:36:28 lampret
72 // For GDB changed single stepping and disabled trap exception.
74 // Revision 1.11 2001/11/13 10:02:21 lampret
75 // Added 'setpc'. Renamed some signals (except_flushpipe into flushpipe etc)
77 // Revision 1.10 2001/11/12 01:45:40 lampret
78 // Moved flag bit into SR. Changed RF enable from constant enable to dynamic enable for read ports.
80 // Revision 1.9 2001/11/10 03:43:57 lampret
83 // Revision 1.8 2001/10/21 17:57:16 lampret
84 // Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
86 // Revision 1.7 2001/10/14 13:12:09 lampret
89 // Revision 1.1.1.1 2001/10/06 10:18:36 igorm
92 // Revision 1.2 2001/08/13 03:36:20 lampret
93 // Added cfg regs. Moved all defines into one defines.v file. More cleanup.
95 // Revision 1.1 2001/08/09 13:39:33 lampret
100 // synopsys translate_off
101 `include "timescale.v"
102 // synopsys translate_on
103 `include "or1200_defines.v"
110 id_freeze
, ex_freeze
, wb_freeze
, flushpipe
, if_insn
, ex_insn
, branch_op
, branch_taken
,
111 rf_addra
, rf_addrb
, rf_rda
, rf_rdb
, alu_op
, mac_op
, shrot_op
, comp_op
, rf_addrw
, rfwb_op
,
112 wb_insn
, simm
, branch_addrofs
, lsu_addrofs
, sel_a
, sel_b
, lsu_op
,
113 multicycle
, spr_addrimm
, wbforw_valid
, sig_syscall
, sig_trap
,
114 force_dslot_fetch
, no_more_dslot
, ex_void
, id_macrc_op
, ex_macrc_op
, rfe
, except_illegal
126 input [31:0] if_insn
;
127 output [31:0] ex_insn
;
128 output [`OR1200_BRANCHOP_WIDTH-1:0] branch_op;
130 output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw;
131 output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addra;
132 output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrb;
135 output [`OR1200_ALUOP_WIDTH-1:0] alu_op;
136 output [`OR1200_MACOP_WIDTH-1:0] mac_op;
137 output [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
138 output [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
139 output [31:0] wb_insn
;
141 output [31:2] branch_addrofs
;
142 output [31:0] lsu_addrofs
;
143 output [`OR1200_SEL_WIDTH-1:0] sel_a;
144 output [`OR1200_SEL_WIDTH-1:0] sel_b;
145 output [`OR1200_LSUOP_WIDTH-1:0] lsu_op;
146 output [`OR1200_COMPOP_WIDTH-1:0] comp_op;
147 output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
148 output [15:0] spr_addrimm
;
152 output force_dslot_fetch
;
153 output no_more_dslot
;
158 output except_illegal
;
161 // Internal wires and regs
163 reg [`OR1200_BRANCHOP_WIDTH-1:0] pre_branch_op;
164 reg [`OR1200_BRANCHOP_WIDTH-1:0] branch_op;
165 reg [`OR1200_ALUOP_WIDTH-1:0] alu_op;
166 reg [`OR1200_MACOP_WIDTH-1:0] mac_op;
167 reg [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
171 reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw;
172 reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] wb_rfaddrw;
173 reg [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
174 reg [31:0] lsu_addrofs
;
175 reg [`OR1200_SEL_WIDTH-1:0] sel_a;
176 reg [`OR1200_SEL_WIDTH-1:0] sel_b;
178 reg [`OR1200_LSUOP_WIDTH-1:0] lsu_op;
179 reg [`OR1200_COMPOP_WIDTH-1:0] comp_op;
180 reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
182 reg [15:0] spr_addrimm
;
190 // Register file read addresses
192 assign rf_addra
= if_insn
[20:16];
193 assign rf_addrb
= if_insn
[15:11];
194 assign rf_rda
= if_insn
[31];
195 assign rf_rdb
= if_insn
[30];
198 // Force fetch of delay slot instruction when jump/branch is preceeded by load/store
202 // assign force_dslot_fetch = ((|pre_branch_op) & (|lsu_op));
203 assign force_dslot_fetch
= 1'b0;
204 assign no_more_dslot
= |branch_op
& !id_void
& branch_taken |
(branch_op
== `OR1200_BRANCHOP_RFE);
205 assign id_void
= (id_insn
[31:26] == `OR1200_OR32_NOP) & id_insn[16];
206 assign ex_void
= (ex_insn
[31:26] == `OR1200_OR32_NOP) & ex_insn[16];
209 // Sign/Zero extension of immediates
211 assign simm
= (imm_signextend
== 1'b1) ?
{{16{id_insn
[15]}}, id_insn
[15:0]} : {{16'b0}, id_insn
[15:0]};
214 // Sign extension of branch offset
216 assign branch_addrofs
= {{4{ex_insn
[25]}}, ex_insn
[25:0]};
219 // l.macrc in ID stage
221 assign id_macrc_op
= (id_insn
[31:26] == `OR1200_OR32_MOVHI) & id_insn[16];
226 assign rfe
= (pre_branch_op
== `OR1200_BRANCHOP_RFE) | (branch_op == `OR1200_BRANCHOP_RFE);
229 // Generation of sel_a
231 always @(rf_addrw
or id_insn
or rfwb_op
or wbforw_valid
or wb_rfaddrw
)
232 if ((id_insn
[20:16] == rf_addrw
) && rfwb_op
[0])
233 sel_a
= `OR1200_SEL_EX_FORW;
234 else if ((id_insn
[20:16] == wb_rfaddrw
) && wbforw_valid
)
235 sel_a
= `OR1200_SEL_WB_FORW;
237 sel_a
= `OR1200_SEL_RF;
240 // Generation of sel_b
242 always @(rf_addrw
or sel_imm
or id_insn
or rfwb_op
or wbforw_valid
or wb_rfaddrw
)
244 sel_b
= `OR1200_SEL_IMM;
245 else if ((id_insn
[15:11] == rf_addrw
) && rfwb_op
[0])
246 sel_b
= `OR1200_SEL_EX_FORW;
247 else if ((id_insn
[15:11] == wb_rfaddrw
) && wbforw_valid
)
248 sel_b
= `OR1200_SEL_WB_FORW;
250 sel_b
= `OR1200_SEL_RF;
253 // l.macrc in EX stage
255 always @(posedge clk
or posedge rst
) begin
257 ex_macrc_op
<= #1 1'b0;
258 else if (!ex_freeze
& id_freeze | flushpipe
)
259 ex_macrc_op
<= #1 1'b0;
261 ex_macrc_op
<= #1 id_macrc_op
;
265 // Decode of spr_addrimm
267 always @(posedge clk
or posedge rst
) begin
269 spr_addrimm
<= #1 16'h0000
;
270 else if (!ex_freeze
& id_freeze | flushpipe
)
271 spr_addrimm
<= #1 16'h0000
;
272 else if (!ex_freeze
) begin
273 case (id_insn
[31:26]) // synopsys parallel_case
276 spr_addrimm
<= #1 id_insn
[15:0];
279 spr_addrimm
<= #1 {id_insn
[25:21], id_insn
[10:0]};
285 // Decode of multicycle
287 always @(id_insn
) begin
288 case (id_insn
[31:26]) // synopsys parallel_case
292 multicycle
= `OR1200_TWO_CYCLES;
296 multicycle
= `OR1200_TWO_CYCLES;
300 multicycle
= `OR1200_TWO_CYCLES;
304 multicycle
= `OR1200_TWO_CYCLES;
308 multicycle
= `OR1200_TWO_CYCLES;
312 multicycle
= `OR1200_TWO_CYCLES;
316 multicycle
= `OR1200_TWO_CYCLES;
320 multicycle
= `OR1200_TWO_CYCLES;
322 // ALU instructions except the one with immediate
324 multicycle
= id_insn
[`OR1200_ALUMCYC_POS];
326 // Single cycle instructions
328 multicycle
= `OR1200_ONE_CYCLE;
336 // Decode of imm_signextend
338 always @(id_insn
) begin
339 case (id_insn
[31:26]) // synopsys parallel_case
343 imm_signextend
= 1'b1;
347 imm_signextend
= 1'b1;
351 imm_signextend
= 1'b1;
355 imm_signextend
= 1'b1;
359 imm_signextend
= 1'b1;
361 // SFXX insns with immediate
363 imm_signextend
= 1'b1;
365 // Instructions with no or zero extended immediate
367 imm_signextend
= 1'b0;
377 always @(lsu_op
or ex_insn
) begin
378 lsu_addrofs
[10:0] = ex_insn
[10:0];
379 case(lsu_op
) // synopsys parallel_case
380 `OR1200_LSUOP_SW, `OR1200_LSUOP_SH, `OR1200_LSUOP_SB :
381 lsu_addrofs
[31:11] = {{16{ex_insn
[25]}}, ex_insn
[25:21]};
383 lsu_addrofs
[31:11] = {{16{ex_insn
[15]}}, ex_insn
[15:11]};
388 // Register file write address
390 always @(posedge clk
or posedge rst
) begin
393 else if (!ex_freeze
& id_freeze
)
394 rf_addrw
<= #1 5'd00;
396 case (pre_branch_op
) // synopsys parallel_case
397 `OR1200_BRANCHOP_JR, `OR1200_BRANCHOP_BAL:
398 rf_addrw
<= #1 5'd09; // link register r9
400 rf_addrw
<= #1 id_insn
[25:21];
405 // rf_addrw in wb stage (used in forwarding logic)
407 always @(posedge clk
or posedge rst
) begin
409 wb_rfaddrw
<= #1 5'd0;
411 wb_rfaddrw
<= #1 rf_addrw
;
415 // Instruction latch in id_insn
417 always @(posedge clk
or posedge rst
) begin
419 id_insn
<= #1 {`OR1200_OR32_NOP, 26'h041_0000};
421 id_insn
<= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // id_insn[16] must be 1
422 else if (!id_freeze
) begin
423 id_insn
<= #1 if_insn
;
424 `ifdef OR1200_VERBOSE
425 // synopsys translate_off
426 $display("%t: id_insn <= %h", $time, if_insn
);
427 // synopsys translate_on
433 // Instruction latch in ex_insn
435 always @(posedge clk
or posedge rst
) begin
437 ex_insn
<= #1 {`OR1200_OR32_NOP, 26'h041_0000};
438 else if (!ex_freeze
& id_freeze | flushpipe
)
439 ex_insn
<= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // ex_insn[16] must be 1
440 else if (!ex_freeze
) begin
441 ex_insn
<= #1 id_insn
;
442 `ifdef OR1200_VERBOSE
443 // synopsys translate_off
444 $display("%t: ex_insn <= %h", $time, id_insn
);
445 // synopsys translate_on
451 // Instruction latch in wb_insn
453 always @(posedge clk
or posedge rst
) begin
455 wb_insn
<= #1 {`OR1200_OR32_NOP, 26'h041_0000};
457 wb_insn
<= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // wb_insn[16] must be 1
458 else if (!wb_freeze
) begin
459 wb_insn
<= #1 ex_insn
;
466 always @(posedge clk
or posedge rst
) begin
469 else if (!id_freeze
) begin
470 case (if_insn
[31:26]) // synopsys parallel_case
492 // l.sys, l.brk and all three sync insns
512 // ALU instructions except the one with immediate
524 // All instructions with immediates
535 // Decode of except_illegal
537 always @(posedge clk
or posedge rst
) begin
539 except_illegal
<= #1 1'b0;
540 else if (!ex_freeze
& id_freeze | flushpipe
)
541 except_illegal
<= #1 1'b0;
542 else if (!ex_freeze
) begin
543 case (id_insn
[31:26]) // synopsys parallel_case
567 `OR1200_OR32_SH_ROTI,
577 except_illegal
<= #1 1'b0;
579 // Illegal and OR1200 unsupported instructions
581 except_illegal
<= #1 1'b1;
591 always @(posedge clk
or posedge rst
) begin
593 alu_op
<= #1 `OR1200_ALUOP_NOP;
594 else if (!ex_freeze
& id_freeze | flushpipe
)
595 alu_op
<= #1 `OR1200_ALUOP_NOP;
596 else if (!ex_freeze
) begin
597 case (id_insn
[31:26]) // synopsys parallel_case
601 alu_op
<= #1 `OR1200_ALUOP_IMM;
605 alu_op
<= #1 `OR1200_ALUOP_IMM;
609 alu_op
<= #1 `OR1200_ALUOP_NOP;
613 alu_op
<= #1 `OR1200_ALUOP_NOP;
617 alu_op
<= #1 `OR1200_ALUOP_MOVHI;
621 alu_op
<= #1 `OR1200_ALUOP_MFSR;
625 alu_op
<= #1 `OR1200_ALUOP_MTSR;
629 alu_op
<= #1 `OR1200_ALUOP_ADD;
633 alu_op
<= #1 `OR1200_ALUOP_ADD;
637 alu_op
<= #1 `OR1200_ALUOP_AND;
641 alu_op
<= #1 `OR1200_ALUOP_OR;
645 alu_op
<= #1 `OR1200_ALUOP_XOR;
649 alu_op
<= #1 `OR1200_ALUOP_MUL;
651 // Shift and rotate insns with immediate
652 `OR1200_OR32_SH_ROTI:
653 alu_op
<= #1 `OR1200_ALUOP_SHROT;
655 // SFXX insns with immediate
657 alu_op
<= #1 `OR1200_ALUOP_COMP;
659 // ALU instructions except the one with immediate
661 alu_op
<= #1 id_insn
[3:0];
665 alu_op
<= #1 `OR1200_ALUOP_COMP;
669 alu_op
<= #1 `OR1200_ALUOP_NOP;
680 always @(posedge clk
or posedge rst
) begin
682 mac_op
<= #1 `OR1200_MACOP_NOP;
683 else if (!ex_freeze
& id_freeze | flushpipe
)
684 mac_op
<= #1 `OR1200_MACOP_NOP;
686 case (id_insn
[31:26]) // synopsys parallel_case
690 mac_op
<= #1 `OR1200_MACOP_MAC;
694 mac_op
<= #1 id_insn
[1:0];
696 // Illegal and OR1200 unsupported instructions
698 mac_op
<= #1 `OR1200_MACOP_NOP;
703 mac_op
<= #1 `OR1200_MACOP_NOP;
707 // Decode of shrot_op
709 always @(posedge clk
or posedge rst
) begin
711 shrot_op
<= #1 `OR1200_SHROTOP_NOP;
712 else if (!ex_freeze
& id_freeze | flushpipe
)
713 shrot_op
<= #1 `OR1200_SHROTOP_NOP;
714 else if (!ex_freeze
) begin
715 shrot_op
<= #1 id_insn
[`OR1200_SHROTOP_POS];
722 always @(posedge clk
or posedge rst
) begin
724 rfwb_op
<= #1 `OR1200_RFWBOP_NOP;
725 else if (!ex_freeze
& id_freeze | flushpipe
)
726 rfwb_op
<= #1 `OR1200_RFWBOP_NOP;
727 else if (!ex_freeze
) begin
728 case (id_insn
[31:26]) // synopsys parallel_case
732 rfwb_op
<= #1 `OR1200_RFWBOP_LR;
736 rfwb_op
<= #1 `OR1200_RFWBOP_LR;
740 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
744 rfwb_op
<= #1 `OR1200_RFWBOP_SPRS;
748 rfwb_op
<= #1 `OR1200_RFWBOP_LSU;
752 rfwb_op
<= #1 `OR1200_RFWBOP_LSU;
756 rfwb_op
<= #1 `OR1200_RFWBOP_LSU;
760 rfwb_op
<= #1 `OR1200_RFWBOP_LSU;
764 rfwb_op
<= #1 `OR1200_RFWBOP_LSU;
768 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
772 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
776 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
780 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
784 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
788 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
790 // Shift and rotate insns with immediate
791 `OR1200_OR32_SH_ROTI:
792 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
794 // ALU instructions except the one with immediate
796 rfwb_op
<= #1 `OR1200_RFWBOP_ALU;
798 // Instructions w/o register-file write-back
800 rfwb_op
<= #1 `OR1200_RFWBOP_NOP;
808 // Decode of pre_branch_op
810 always @(posedge clk
or posedge rst
) begin
812 pre_branch_op
<= #1 `OR1200_BRANCHOP_NOP;
814 pre_branch_op
<= #1 `OR1200_BRANCHOP_NOP;
815 else if (!id_freeze
) begin
816 case (if_insn
[31:26]) // synopsys parallel_case
820 pre_branch_op
<= #1 `OR1200_BRANCHOP_BAL;
824 pre_branch_op
<= #1 `OR1200_BRANCHOP_BAL;
828 pre_branch_op
<= #1 `OR1200_BRANCHOP_JR;
832 pre_branch_op
<= #1 `OR1200_BRANCHOP_JR;
836 pre_branch_op
<= #1 `OR1200_BRANCHOP_BNF;
840 pre_branch_op
<= #1 `OR1200_BRANCHOP_BF;
844 pre_branch_op
<= #1 `OR1200_BRANCHOP_RFE;
846 // Non branch instructions
848 pre_branch_op
<= #1 `OR1200_BRANCHOP_NOP;
855 // Generation of branch_op
857 always @(posedge clk
or posedge rst
)
859 branch_op
<= #1 `OR1200_BRANCHOP_NOP;
860 else if (!ex_freeze
& id_freeze | flushpipe
)
861 branch_op
<= #1 `OR1200_BRANCHOP_NOP;
863 branch_op
<= #1 pre_branch_op
;
868 always @(posedge clk
or posedge rst
) begin
870 lsu_op
<= #1 `OR1200_LSUOP_NOP;
871 else if (!ex_freeze
& id_freeze | flushpipe
)
872 lsu_op
<= #1 `OR1200_LSUOP_NOP;
873 else if (!ex_freeze
) begin
874 case (id_insn
[31:26]) // synopsys parallel_case
878 lsu_op
<= #1 `OR1200_LSUOP_LWZ;
882 lsu_op
<= #1 `OR1200_LSUOP_LBZ;
886 lsu_op
<= #1 `OR1200_LSUOP_LBS;
890 lsu_op
<= #1 `OR1200_LSUOP_LHZ;
894 lsu_op
<= #1 `OR1200_LSUOP_LHS;
898 lsu_op
<= #1 `OR1200_LSUOP_SW;
902 lsu_op
<= #1 `OR1200_LSUOP_SB;
906 lsu_op
<= #1 `OR1200_LSUOP_SH;
908 // Non load/store instructions
910 lsu_op
<= #1 `OR1200_LSUOP_NOP;
919 always @(posedge clk
or posedge rst
) begin
922 end else if (!ex_freeze
& id_freeze | flushpipe
)
925 comp_op
<= #1 id_insn
[24:21];
931 always @(posedge clk
or posedge rst
) begin
933 sig_syscall
<= #1 1'b0;
934 else if (!ex_freeze
& id_freeze | flushpipe
)
935 sig_syscall
<= #1 1'b0;
936 else if (!ex_freeze
) begin
937 `ifdef OR1200_VERBOSE
938 // synopsys translate_off
939 if (id_insn
[31:23] == {`OR1200_OR32_XSYNC, 3'b000})
940 $display("Generating sig_syscall");
941 // synopsys translate_on
943 sig_syscall
<= #1 (id_insn
[31:23] == {`OR1200_OR32_XSYNC, 3'b000});
950 always @(posedge clk
or posedge rst
) begin
953 else if (!ex_freeze
& id_freeze | flushpipe
)
955 else if (!ex_freeze
) begin
956 `ifdef OR1200_VERBOSE
957 // synopsys translate_off
958 if (id_insn
[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
959 $display("Generating sig_trap");
960 // synopsys translate_on
962 sig_trap
<= #1 (id_insn
[31:23] == {`OR1200_OR32_XSYNC, 3'b010});