1 |
2 |
smjoshua |
//////////////////////////////////////////////////////////////////
|
2 |
|
|
// //
|
3 |
|
|
// OoOPs Core Instruction Decode module //
|
4 |
|
|
// //
|
5 |
|
|
// This file is part of the OoOPs project //
|
6 |
|
|
// http://www.opencores.org/project,oops //
|
7 |
|
|
// //
|
8 |
|
|
// Description: //
|
9 |
|
|
// Handles basic decoding of instruction type and register //
|
10 |
|
|
// sources and destinations for Dispatch stages. //
|
11 |
|
|
// We could do full instruction decoding in this stage, but //
|
12 |
|
|
// to save on pipeline flops we will only decode what is needed//
|
13 |
|
|
// for dispatch. We can use the issue stage to do necessary //
|
14 |
|
|
// decoding for each functional unit. //
|
15 |
|
|
// //
|
16 |
|
|
// Author(s): //
|
17 |
|
|
// - Joshua Smith, smjoshua@umich.edu //
|
18 |
|
|
// //
|
19 |
|
|
//////////////////////////////////////////////////////////////////
|
20 |
|
|
// //
|
21 |
|
|
// Copyright (C) 2012 Authors and OPENCORES.ORG //
|
22 |
|
|
// //
|
23 |
|
|
// This source file may be used and distributed without //
|
24 |
|
|
// restriction provided that this copyright statement is not //
|
25 |
|
|
// removed from the file and that any derivative work contains //
|
26 |
|
|
// the original copyright notice and the associated disclaimer. //
|
27 |
|
|
// //
|
28 |
|
|
// This source file is free software; you can redistribute it //
|
29 |
|
|
// and/or modify it under the terms of the GNU Lesser General //
|
30 |
|
|
// Public License as published by the Free Software Foundation; //
|
31 |
|
|
// either version 2.1 of the License, or (at your option) any //
|
32 |
|
|
// later version. //
|
33 |
|
|
// //
|
34 |
|
|
// This source is distributed in the hope that it will be //
|
35 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied //
|
36 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
|
37 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more //
|
38 |
|
|
// details. //
|
39 |
|
|
// //
|
40 |
|
|
// You should have received a copy of the GNU Lesser General //
|
41 |
|
|
// Public License along with this source; if not, download it //
|
42 |
|
|
// from http://www.opencores.org/lgpl.shtml //
|
43 |
|
|
// //
|
44 |
|
|
//////////////////////////////////////////////////////////////////
|
45 |
|
|
`include "ooops_defs.v"
|
46 |
|
|
|
47 |
|
|
module id_stage (
|
48 |
|
|
input wire clk,
|
49 |
|
|
input wire rst,
|
50 |
|
|
|
51 |
|
|
// Flush/stall interface
|
52 |
|
|
input wire rob_pipe_flush,
|
53 |
|
|
input wire ds_stall,
|
54 |
|
|
|
55 |
|
|
// Interface to IF stage
|
56 |
|
|
input wire if_id_valid,
|
57 |
|
|
input wire [`INSTR_SZ-1:0] if_id_instr,
|
58 |
|
|
input wire [`ADDR_SZ-1:0] if_id_fpc,
|
59 |
|
|
input wire [`BP_SZ-1:0] if_id_bprd_info,
|
60 |
|
|
|
61 |
|
|
// Interface to Dispatch stage
|
62 |
|
|
output wire id_ds1_valid,
|
63 |
|
|
output wire [`ADDR_SZ-1:0] id_ds1_fpc,
|
64 |
|
|
output wire id_ds1_in_dly_slot,
|
65 |
|
|
output wire [`DEC_BUS_SZ-1:0] id_ds1_dec_bus,
|
66 |
|
|
output wire [`BP_SZ-1:0] id_ds1_bprd_info
|
67 |
|
|
);
|
68 |
|
|
|
69 |
|
|
// Internal wires
|
70 |
|
|
wire id_type_br;
|
71 |
|
|
wire id_type_ldst;
|
72 |
|
|
wire id_type_multdiv;
|
73 |
|
|
wire id_type_alu;
|
74 |
|
|
wire [`DEC_BUS_SZ-1:0] id_dec_bus;
|
75 |
|
|
wire id_rs_need;
|
76 |
|
|
wire id_rt_need;
|
77 |
|
|
wire id_rd_write;
|
78 |
|
|
wire [`REG_IDX_SZ-1:0] id_rs_idx;
|
79 |
|
|
wire [`REG_IDX_SZ-1:0] id_rt_idx;
|
80 |
|
|
wire [`REG_IDX_SZ-1:0] id_rd_idx;
|
81 |
|
|
|
82 |
|
|
// Handle stalling indications
|
83 |
|
|
wire id_stall = ds_stall;
|
84 |
|
|
|
85 |
|
|
// Determine basic instruction type
|
86 |
|
|
wire id_instr_special = ~(|if_id_instr[31:26]);
|
87 |
|
|
|
88 |
|
|
// MULT/DIV
|
89 |
|
|
wire id_mult = (id_instr_special & if_id_instr[5:1]==5'b01100);
|
90 |
|
|
wire id_div = (id_instr_special & if_id_instr[5:1]==5'b01101);
|
91 |
|
|
assign id_type_multdiv = id_mult | id_div;
|
92 |
|
|
|
93 |
|
|
// LDST
|
94 |
|
|
wire id_mem_ld = (if_id_instr[31:29]==3'b100) && (~if_id_instr[27] | (if_id_instr[28:26]==3'b011));
|
95 |
|
|
wire id_mem_st = (if_id_instr[31:28]==4'b1010) && (if_id_instr[27:26]!=2'b10);
|
96 |
|
|
assign id_type_ldst = id_mem_ld || id_mem_st;
|
97 |
|
|
|
98 |
|
|
// Branch
|
99 |
|
|
wire id_br_beq = (if_id_instr[31:27]==5'b00010);
|
100 |
|
|
wire id_br_bge = (if_id_instr[31:26]==6'b000001) && (if_id_instr[20:17]==4'b0000);
|
101 |
|
|
wire id_br_bgt = (if_id_instr[31:27]==5'b00011) && (if_id_instr[20:16]==5'b00000);
|
102 |
|
|
wire id_br_neg = (id_br_beq && if_id_instr[26]) || // BNE
|
103 |
|
|
(id_br_bge && if_id_instr[17]) || // BLTZ
|
104 |
|
|
(id_br_bgt && !if_id_instr[26]); // BLEZ
|
105 |
|
|
wire id_br_j = (if_id_instr[31:27]==5'b00001);
|
106 |
|
|
wire id_br_jr = id_instr_special && (if_id_instr[5:1]==5'b00100);
|
107 |
|
|
wire id_br_link = (id_br_bge && if_id_instr[20]) || // BGEZAL, BLTZAL
|
108 |
|
|
(id_br_j && if_id_instr[16]); // JAL
|
109 |
|
|
wire id_br_link_reg = (id_br_jr && if_id_instr[0]); // JALR
|
110 |
|
|
wire id_except = id_instr_special && (if_id_instr[5:1]==5'b00110);
|
111 |
|
|
//wire id_break = id_except && if_id_instr[0];
|
112 |
|
|
wire id_syscall = id_except && !if_id_instr[0];
|
113 |
|
|
assign id_type_br = (id_br_beq | id_br_bge | id_br_bgt | id_br_j | id_br_jr | id_except);
|
114 |
|
|
|
115 |
|
|
// ALU
|
116 |
|
|
wire id_alu_shift = id_instr_special && (if_id_instr[5:3]==3'b000);
|
117 |
|
|
wire id_alu_shift_imm = id_alu_shift & !if_id_instr[2];
|
118 |
|
|
wire id_alu_cmp = (id_instr_special && if_id_instr[5:1]==5'b10101) || // SLT/SLTU
|
119 |
|
|
(if_id_instr[31:27]==5'b00101); // SLTI/SLTIU
|
120 |
|
|
wire id_alu_log_reg = id_instr_special && (if_id_instr[5:2]==4'b1001);
|
121 |
|
|
wire id_alu_log_imm = (if_id_instr[31:28]==4'b0011) && !(&if_id_instr[27:26]);
|
122 |
|
|
wire id_hilo_mov = id_instr_special & (if_id_instr[5:2]==4'b0100);
|
123 |
|
|
wire id_mfhi = id_hilo_mov & (if_id_instr[1:0]==2'b00);
|
124 |
|
|
wire id_mflo = id_hilo_mov & (if_id_instr[1:0]==2'b10);
|
125 |
|
|
wire id_mthi = id_hilo_mov & (if_id_instr[1:0]==2'b01);
|
126 |
|
|
wire id_mtlo = id_hilo_mov & (if_id_instr[1:0]==2'b11);
|
127 |
|
|
wire id_alu_add_sub = (id_instr_special && (if_id_instr[5:2]==4'b1000)) || // ADD/SUB Reg
|
128 |
|
|
(if_id_instr[31:27]==5'b00100); // ADDI
|
129 |
|
|
wire id_alu_lui = (if_id_instr[31:26]==6'b001111);
|
130 |
|
|
|
131 |
|
|
// Coprocessor ops included
|
132 |
|
|
wire id_cp_op = (if_id_instr[31:26]==6'b010000) && !(|if_id_instr[25:24]) && !(|if_id_instr[22:21]);
|
133 |
|
|
wire id_cp_to = id_cp_op && if_id_instr[23];
|
134 |
|
|
//wire id_cp_num = if_id_instr[27:26];
|
135 |
|
|
|
136 |
|
|
assign id_type_alu = id_alu_shift | id_alu_cmp | id_alu_log_reg | id_alu_log_imm |
|
137 |
|
|
id_type_br | id_hilo_mov | id_alu_add_sub | id_alu_lui | id_cp_op;
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
|
141 |
|
|
// Determine register indices
|
142 |
|
|
// Figure out whether operands require register values.
|
143 |
|
|
// This is so we know whether to stall for forwarded data for an operand
|
144 |
|
|
// For ALU operations, all but LUI need reg_s. Immediate instructions don't need reg_t
|
145 |
|
|
assign id_rs_need = (id_type_alu & !id_alu_lui & !id_br_j) |
|
146 |
|
|
(id_alu_shift & !id_alu_shift_imm) |
|
147 |
|
|
(id_div | id_mult) |
|
148 |
|
|
(id_type_ldst);
|
149 |
|
|
assign id_rt_need = (id_type_alu & !id_alu_imm) | id_type_multdiv | id_br_beq | id_cp_to | id_mem_st;
|
150 |
|
|
assign id_rd_wr = !(id_mem_st | (id_type_br & !id_br_link) | id_cp_to | id_syscall);
|
151 |
|
|
|
152 |
|
|
// Handle moves to/from HI and LO
|
153 |
|
|
assign id_rs_idx = id_mfhi ? `REG_IDX_SZ'd32 :
|
154 |
|
|
id_mflo ? `REG_IDX_SZ'd33 : id_reg_s_idx_pre;
|
155 |
|
|
assign id_rt_idx = id_reg_t_idx_pre;
|
156 |
|
|
assign id_rd_idx = id_mthi ? `REG_IDX_SZ'd32 :
|
157 |
|
|
id_mtlo ? `REG_IDX_SZ'd33 : id_reg_d_idx_pre;
|
158 |
|
|
|
159 |
|
|
// Determine if instructions are in a delay slot
|
160 |
|
|
// This is needed by the ROB in case a branch is mispredicted so we know not to flush the delay instruction.
|
161 |
|
|
wire id_in_dly_slot_set = !id_stall & (if_id_valid & id_type_br);
|
162 |
|
|
wire id_in_dly_slot_rst = !id_stall & (if_id_valid & id_in_dly_slot);
|
163 |
|
|
wire id_in_dly_slot_in = (id_in_dly_slot_set | id_in_dly_slot) & !id_in_dly_slot_rst;
|
164 |
|
|
MDFFR #(1) id_in_dly_slot_ff (clk, rst, 1'b0, id_in_dly_slot_in, id_in_dly_slot);
|
165 |
|
|
|
166 |
|
|
wire id_in_dly_slot = if_id_valid & id_in_dly_slot;
|
167 |
|
|
|
168 |
|
|
// Put together decode bus
|
169 |
|
|
assign id_dec_bus[`DEC_REG_D_IDX] = id_rd_idx;
|
170 |
|
|
assign id_dec_bus[`DEC_REG_T_IDX] = id_rt_idx;
|
171 |
|
|
assign id_dec_bus[`DEC_REG_S_IDX] = id_rs_idx;
|
172 |
|
|
assign id_dec_bus[`DEC_REG_D_WR] = id_rd_wr;
|
173 |
|
|
assign id_dec_bus[`DEC_REG_T_NEED] = id_rt_need;
|
174 |
|
|
assign id_dec_bus[`DEC_REG_S_NEED] = id_rs_need;
|
175 |
|
|
assign id_dec_bus[`DEC_TYPE_CP] = id_cp_op;
|
176 |
|
|
assign id_dec_bus[`DEC_TYPE_BR] = id_type_br;
|
177 |
|
|
assign id_dec_bus[`DEC_TYPE_LDST] = id_type_ldst;
|
178 |
|
|
assign id_dec_bus[`DEC_TYPE_MULTDIV] = id_type_multdiv;
|
179 |
|
|
assign id_dec_bus[`DEC_TYPE_ALU] = id_type_alu;
|
180 |
|
|
|
181 |
|
|
wire id_valid = if_id_valid & !rob_pipe_flush;
|
182 |
|
|
|
183 |
|
|
// Flop outputs to DS stage
|
184 |
|
|
MDFFLR #(1) id_ds1_valid_ff (clk, rst, !id_stall, 1'b0, id_valid, id_ds1_valid);
|
185 |
|
|
MDFFL #(`ADDR_SZ) id_ds1_fpc_ff (clk, if_id_valid, if_id_fpc, id_ds1_fpc);
|
186 |
|
|
MDFFLR #(1) id_ds1_in_dly_slot_ff (clk, rst, if_id_valid, 1'b0, id_in_dly_slot, id_ds1_in_dly_slot);
|
187 |
|
|
MDFFL #(`DEC_BUS_SZ) id_ds1_dec_bus_ff (clk, if_id_valid, id_dec_bus, id_ds1_dec_bus);
|
188 |
|
|
MDFFL #(`BP_SZ) id_ds1_bprd_info_ff (clk, if_id_valid, if_id_bprd_info, id_ds1_bprd_info);
|
189 |
|
|
|
190 |
|
|
endmodule
|