OpenCores
URL https://opencores.org/ocsvn/m1_core/m1_core/trunk

Subversion Repositories m1_core

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 32 to Rev 33
    Reverse comparison

Rev 32 → Rev 33

/trunk/hdl/rtl/m1_core/m1_mmu.v
1,98 → 1,82
/*
* Simply RISC M1 Memory Management Unit
*
* It will include the following components:
* - Instruction Cache
* - Data Cache
* - TLB
* but for now it's just a fake MMU.
*
* This block converts Harvard architecture requests to access the
* small internal prefetch buffer, and just in case the external
* Wishbone bus.
* Memory size is 256 word * 4 byte = 1024 byte,
* so 10 address bits are required => [9:0]
* and being the lower 2 bits unused the offset in memory is [9:2].
*/
 
module m1_mmu (
sys_clock_i, sys_reset_i,
imem_addr_i, imem_data_o, imem_read_i, imem_busy_o,
dmem_addr_i, dmem_data_o, dmem_data_i, dmem_read_i, dmem_write_i, dmem_busy_o ,dmem_sel_i
);
 
// System
input sys_clock_i, sys_reset_i;
// Instruction Memory
input[31:0] imem_addr_i;
output[31:0] imem_data_o;
input imem_read_i;
output imem_busy_o;
// System
input sys_clock_i, // System Clock
input sys_reset_i, // System Reset
 
// Data Memory
input[31:0] dmem_addr_i;
output[31:0] dmem_data_o;
input[31:0] dmem_data_i;
input dmem_read_i;
input dmem_write_i;
output dmem_busy_o;
// Instruction Memory
input imem_read_i, // I$ Read
input[31:0] imem_addr_i, // I$ Address
output imem_done_o, // I$ Done
output[31:0] imem_data_o, // I$ Data
 
// Fake Instruction and Data Memories
reg[31:0] imem_data[0:1023]; // 4KB I$
reg[31:0] dmem_data[0:255]; // 1KB D$
// Data Memory
input dmem_read_i, // D$ Read
input dmem_write_i, // D$ Write
input[31:0] dmem_addr_i, // D$ Address
input[31:0] dmem_data_i, // D$ Write Data
input[3:0] dmem_sel_i, // D$ Byte selector
output dmem_done_o, // D$ Done
output[31:0] dmem_data_o, // D$ Read Data
 
//Selector
input[3:0] dmem_sel_i;
reg[31:0] data_temp;
// Wishbone Master interface
output wb_cyc_o, // Cycle Start
output wb_stb_o, // Strobe Request
output wb_we_o, // Write Enable
output[31:0] wb_adr_o, // Address Bus
output[31:0] wb_dat_o, // Data Out
output[3:0] wb_sel_o, // Byte Select
input wb_ack_i, // Ack
input[31:0] wb_dat_i // Data In
 
// Initialize fake memories
integer i;
initial begin
// I$ is initialized from file
$readmemh("code.txt", imem_data);
);
 
// D$ defaults to zeroes
for(i=0; i<256; i=i+1) dmem_data[i] = 0;
end
/*
* Registers
*/
 
assign imem_busy_o = 0;
assign dmem_busy_o = 0;
// Prefetch buffer
reg[31:0] MEM[255:0];
 
// Initialize memory content
initial begin
`include "m1_mmu_initial.vh"
end
 
assign imem_data_o = imem_data[{2'b00, imem_addr_i[31:2]}];
assign dmem_data_o = dmem_data[{2'b00, dmem_addr_i[31:2]}];
/*
* Wires
*/
 
// See if there are pending requests
wire access_pending_imem = imem_read_i;
wire access_pending_dmem = 0;
wire access_pending_ext = (dmem_read_i || dmem_write_i);
 
always @(dmem_write_i or dmem_read_i) begin
// Default grant for memories
assign imem_done_o = access_pending_imem;
assign dmem_done_o = access_pending_dmem || (access_pending_ext && wb_ack_i);
 
if(dmem_write_i) begin
// Set Wishbone outputs
assign wb_cyc_o = access_pending_ext;
assign wb_stb_o = access_pending_ext;
assign wb_we_o = access_pending_ext && dmem_write_i;
assign wb_sel_o = dmem_sel_i;
assign wb_adr_o = dmem_addr_i;
assign wb_dat_o = dmem_data_i;
 
if(dmem_sel_i[0]) begin
data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
data_temp[7:0] = dmem_data_i[7:0];
dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
end
if(dmem_sel_i[1]) begin
data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
data_temp[15:8] = dmem_data_i[15:8];
dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
end
if(dmem_sel_i[2]) begin
data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
data_temp[24:16] = dmem_data_i[24:16];
dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
end
if(dmem_sel_i[3]) begin
data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
data_temp[31:24] = dmem_data_i[31:24];
dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
end
$display("INFO: MEMH(%m): WRITE_ADDR=%X, WRITE_DATA=%X", dmem_addr_i, dmem_data_i);
end
// Return read data
assign imem_data_o = MEM[imem_addr_i[9:2]];
assign dmem_data_o = wb_dat_i;
 
 
if(dmem_read_i) begin
$display("INFO: MEMH(%m): READ_ADDR=%X, READ_DATA=%X", dmem_addr_i, dmem_data[{2'b00, dmem_addr_i[31:2]}]);
end
end
endmodule
 
/trunk/hdl/rtl/m1_core/m1_mmu_initial.vh
0,0 → 1,257
/* THIS FILE IS GENERATED AUTOMATICALLY BY THE compile_test SCRIPT */
MEM[0] <= 32'h201d1000;
MEM[1] <= 32'h3c1fdead;
MEM[2] <= 32'h37ffbeef;
MEM[3] <= 32'h00000000;
MEM[4] <= 32'h27bdffe8;
MEM[5] <= 32'hafbe0010;
MEM[6] <= 32'h03a0f021;
MEM[7] <= 32'h3c02faba;
MEM[8] <= 32'h34421210;
MEM[9] <= 32'hafc20008;
MEM[10] <= 32'h8fc30008;
MEM[11] <= 32'h24020048;
MEM[12] <= 32'hac620000;
MEM[13] <= 32'h8fc30008;
MEM[14] <= 32'h24020065;
MEM[15] <= 32'hac620000;
MEM[16] <= 32'h8fc30008;
MEM[17] <= 32'h2402006c;
MEM[18] <= 32'hac620000;
MEM[19] <= 32'h8fc30008;
MEM[20] <= 32'h2402006c;
MEM[21] <= 32'hac620000;
MEM[22] <= 32'h8fc30008;
MEM[23] <= 32'h2402006f;
MEM[24] <= 32'hac620000;
MEM[25] <= 32'h8fc30008;
MEM[26] <= 32'h24020021;
MEM[27] <= 32'hac620000;
MEM[28] <= 32'h8fc30008;
MEM[29] <= 32'h2402000a;
MEM[30] <= 32'hac620000;
MEM[31] <= 32'h00001021;
MEM[32] <= 32'h03c0e821;
MEM[33] <= 32'h8fbe0010;
MEM[34] <= 32'h27bd0018;
MEM[35] <= 32'h03e00008;
MEM[36] <= 32'h00000000;
MEM[37] <= 32'h00000000;
MEM[38] <= 32'h00000000;
MEM[39] <= 32'h00000000;
MEM[40] <= 32'h00000000;
MEM[41] <= 32'h00000000;
MEM[42] <= 32'h00000000;
MEM[43] <= 32'h00000000;
MEM[44] <= 32'h00000000;
MEM[45] <= 32'h00000000;
MEM[46] <= 32'h00000000;
MEM[47] <= 32'h00000000;
MEM[48] <= 32'h00000000;
MEM[49] <= 32'h00000000;
MEM[50] <= 32'h00000000;
MEM[51] <= 32'h00000000;
MEM[52] <= 32'h00000000;
MEM[53] <= 32'h00000000;
MEM[54] <= 32'h00000000;
MEM[55] <= 32'h00000000;
MEM[56] <= 32'h00000000;
MEM[57] <= 32'h00000000;
MEM[58] <= 32'h00000000;
MEM[59] <= 32'h00000000;
MEM[60] <= 32'h00000000;
MEM[61] <= 32'h00000000;
MEM[62] <= 32'h00000000;
MEM[63] <= 32'h00000000;
MEM[64] <= 32'h00000000;
MEM[65] <= 32'h00000000;
MEM[66] <= 32'h00000000;
MEM[67] <= 32'h00000000;
MEM[68] <= 32'h00000000;
MEM[69] <= 32'h00000000;
MEM[70] <= 32'h00000000;
MEM[71] <= 32'h00000000;
MEM[72] <= 32'h00000000;
MEM[73] <= 32'h00000000;
MEM[74] <= 32'h00000000;
MEM[75] <= 32'h00000000;
MEM[76] <= 32'h00000000;
MEM[77] <= 32'h00000000;
MEM[78] <= 32'h00000000;
MEM[79] <= 32'h00000000;
MEM[80] <= 32'h00000000;
MEM[81] <= 32'h00000000;
MEM[82] <= 32'h00000000;
MEM[83] <= 32'h00000000;
MEM[84] <= 32'h00000000;
MEM[85] <= 32'h00000000;
MEM[86] <= 32'h00000000;
MEM[87] <= 32'h00000000;
MEM[88] <= 32'h00000000;
MEM[89] <= 32'h00000000;
MEM[90] <= 32'h00000000;
MEM[91] <= 32'h00000000;
MEM[92] <= 32'h00000000;
MEM[93] <= 32'h00000000;
MEM[94] <= 32'h00000000;
MEM[95] <= 32'h00000000;
MEM[96] <= 32'h00000000;
MEM[97] <= 32'h00000000;
MEM[98] <= 32'h00000000;
MEM[99] <= 32'h00000000;
MEM[100] <= 32'h00000000;
MEM[101] <= 32'h00000000;
MEM[102] <= 32'h00000000;
MEM[103] <= 32'h00000000;
MEM[104] <= 32'h00000000;
MEM[105] <= 32'h00000000;
MEM[106] <= 32'h00000000;
MEM[107] <= 32'h00000000;
MEM[108] <= 32'h00000000;
MEM[109] <= 32'h00000000;
MEM[110] <= 32'h00000000;
MEM[111] <= 32'h00000000;
MEM[112] <= 32'h00000000;
MEM[113] <= 32'h00000000;
MEM[114] <= 32'h00000000;
MEM[115] <= 32'h00000000;
MEM[116] <= 32'h00000000;
MEM[117] <= 32'h00000000;
MEM[118] <= 32'h00000000;
MEM[119] <= 32'h00000000;
MEM[120] <= 32'h00000000;
MEM[121] <= 32'h00000000;
MEM[122] <= 32'h00000000;
MEM[123] <= 32'h00000000;
MEM[124] <= 32'h00000000;
MEM[125] <= 32'h00000000;
MEM[126] <= 32'h00000000;
MEM[127] <= 32'h00000000;
MEM[128] <= 32'h00000000;
MEM[129] <= 32'h00000000;
MEM[130] <= 32'h00000000;
MEM[131] <= 32'h00000000;
MEM[132] <= 32'h00000000;
MEM[133] <= 32'h00000000;
MEM[134] <= 32'h00000000;
MEM[135] <= 32'h00000000;
MEM[136] <= 32'h00000000;
MEM[137] <= 32'h00000000;
MEM[138] <= 32'h00000000;
MEM[139] <= 32'h00000000;
MEM[140] <= 32'h00000000;
MEM[141] <= 32'h00000000;
MEM[142] <= 32'h00000000;
MEM[143] <= 32'h00000000;
MEM[144] <= 32'h00000000;
MEM[145] <= 32'h00000000;
MEM[146] <= 32'h00000000;
MEM[147] <= 32'h00000000;
MEM[148] <= 32'h00000000;
MEM[149] <= 32'h00000000;
MEM[150] <= 32'h00000000;
MEM[151] <= 32'h00000000;
MEM[152] <= 32'h00000000;
MEM[153] <= 32'h00000000;
MEM[154] <= 32'h00000000;
MEM[155] <= 32'h00000000;
MEM[156] <= 32'h00000000;
MEM[157] <= 32'h00000000;
MEM[158] <= 32'h00000000;
MEM[159] <= 32'h00000000;
MEM[160] <= 32'h00000000;
MEM[161] <= 32'h00000000;
MEM[162] <= 32'h00000000;
MEM[163] <= 32'h00000000;
MEM[164] <= 32'h00000000;
MEM[165] <= 32'h00000000;
MEM[166] <= 32'h00000000;
MEM[167] <= 32'h00000000;
MEM[168] <= 32'h00000000;
MEM[169] <= 32'h00000000;
MEM[170] <= 32'h00000000;
MEM[171] <= 32'h00000000;
MEM[172] <= 32'h00000000;
MEM[173] <= 32'h00000000;
MEM[174] <= 32'h00000000;
MEM[175] <= 32'h00000000;
MEM[176] <= 32'h00000000;
MEM[177] <= 32'h00000000;
MEM[178] <= 32'h00000000;
MEM[179] <= 32'h00000000;
MEM[180] <= 32'h00000000;
MEM[181] <= 32'h00000000;
MEM[182] <= 32'h00000000;
MEM[183] <= 32'h00000000;
MEM[184] <= 32'h00000000;
MEM[185] <= 32'h00000000;
MEM[186] <= 32'h00000000;
MEM[187] <= 32'h00000000;
MEM[188] <= 32'h00000000;
MEM[189] <= 32'h00000000;
MEM[190] <= 32'h00000000;
MEM[191] <= 32'h00000000;
MEM[192] <= 32'h00000000;
MEM[193] <= 32'h00000000;
MEM[194] <= 32'h00000000;
MEM[195] <= 32'h00000000;
MEM[196] <= 32'h00000000;
MEM[197] <= 32'h00000000;
MEM[198] <= 32'h00000000;
MEM[199] <= 32'h00000000;
MEM[200] <= 32'h00000000;
MEM[201] <= 32'h00000000;
MEM[202] <= 32'h00000000;
MEM[203] <= 32'h00000000;
MEM[204] <= 32'h00000000;
MEM[205] <= 32'h00000000;
MEM[206] <= 32'h00000000;
MEM[207] <= 32'h00000000;
MEM[208] <= 32'h00000000;
MEM[209] <= 32'h00000000;
MEM[210] <= 32'h00000000;
MEM[211] <= 32'h00000000;
MEM[212] <= 32'h00000000;
MEM[213] <= 32'h00000000;
MEM[214] <= 32'h00000000;
MEM[215] <= 32'h00000000;
MEM[216] <= 32'h00000000;
MEM[217] <= 32'h00000000;
MEM[218] <= 32'h00000000;
MEM[219] <= 32'h00000000;
MEM[220] <= 32'h00000000;
MEM[221] <= 32'h00000000;
MEM[222] <= 32'h00000000;
MEM[223] <= 32'h00000000;
MEM[224] <= 32'h00000000;
MEM[225] <= 32'h00000000;
MEM[226] <= 32'h00000000;
MEM[227] <= 32'h00000000;
MEM[228] <= 32'h00000000;
MEM[229] <= 32'h00000000;
MEM[230] <= 32'h00000000;
MEM[231] <= 32'h00000000;
MEM[232] <= 32'h00000000;
MEM[233] <= 32'h00000000;
MEM[234] <= 32'h00000000;
MEM[235] <= 32'h00000000;
MEM[236] <= 32'h00000000;
MEM[237] <= 32'h00000000;
MEM[238] <= 32'h00000000;
MEM[239] <= 32'h00000000;
MEM[240] <= 32'h00000000;
MEM[241] <= 32'h00000000;
MEM[242] <= 32'h00000000;
MEM[243] <= 32'h00000000;
MEM[244] <= 32'h00000000;
MEM[245] <= 32'h00000000;
MEM[246] <= 32'h00000000;
MEM[247] <= 32'h00000000;
MEM[248] <= 32'h00000000;
MEM[249] <= 32'h00000000;
MEM[250] <= 32'h00000000;
MEM[251] <= 32'h00000000;
MEM[252] <= 32'h00000000;
MEM[253] <= 32'h00000000;
MEM[254] <= 32'h00000000;
MEM[255] <= 32'h00000000;
/trunk/hdl/rtl/m1_core/m1_alu.v
0,0 → 1,49
/*
* Simply RISC M1 Arithmetic-Logic Unit
*
* Simple RTL-level ALU with Alternating Bit Protocol (ABP) interface.
*/
 
`include "m1_defs.vh"
 
// Combinational ALU with 32-bit operands
module m1_alu(
input[31:0] a_i, // Operands A
input[31:0] b_i, // Operands B
input[4:0] func_i, // Function to be performed
input signed_i, // Operation is signed
output reg[31:0] result_o, // Result
output carry_o // Carry bit
);
 
// Carry is currently unused
assign carry_o = 0;
 
// ALU Logic
always @(a_i or b_i or func_i or signed_i) begin
case(func_i)
`ALU_OP_SLL: result_o = a_i << b_i[4:0];
`ALU_OP_SRL: result_o = a_i >> b_i[4:0];
`ALU_OP_SRA: result_o = {{32{a_i[31]}}, a_i } >> b_i[4:0];
`ALU_OP_ADD: result_o = a_i + b_i;
`ALU_OP_SUB: result_o = a_i - b_i;
`ALU_OP_AND: result_o = a_i & b_i;
`ALU_OP_OR: result_o = a_i | b_i;
`ALU_OP_XOR: result_o = a_i ^ b_i;
`ALU_OP_NOR: result_o = ~(a_i | b_i);
`ALU_OP_SEQ: result_o = (a_i == b_i) ? 32'b1 : 32'b0;
`ALU_OP_SNE: result_o = (a_i != b_i) ? 32'b1 : 32'b0;
`ALU_OP_SLT: if(signed_i) result_o = ({~a_i[31],a_i[30:0]} < {~b_i[31],b_i[30:0]}) ? 32'b1 : 32'b0;
else result_o = a_i < b_i;
`ALU_OP_SLE: if ((a_i[31] == 1'b1) || (a_i == 32'b0)) result_o = 32'b1;
else result_o = 32'b0;
`ALU_OP_SGT: if ((a_i[31] == 1'b0) && (a_i != 32'b0)) result_o = 32'b1;
else result_o = 32'b0;
`ALU_OP_SGE: if(signed_i) result_o = ({~a_i[31],a_i[30:0]} >= {~b_i[31],b_i[30:0]}) ? 32'b1 : 32'b0;
else result_o = a_i >= b_i;
default: result_o = 32'b0;
endcase
end
 
endmodule
 
/trunk/hdl/rtl/m1_core/m1_div.v
0,0 → 1,82
/*
* Simply RISC M1 Divider
*
* Simple RTL-level divider with Alternating Bit Protocol (ABP) interface.
*/
 
// 32-bit / 32-bit Integer Divider (this version is not optimized and always takes 32 cycles)
module m1_div(
input sys_reset_i, // System Reset
input sys_clock_i, // System Clock
input[31:0] a_i, // Operand A
input[31:0] b_i, // Operand B
input signed_i, // If division is signed
output reg[31:0] quotient_o, // Quotient of division
output reg[31:0] remainder_o, // Remainder of division
input abp_req_i, // ABP Request
output reg abp_ack_o // ABP Acknowledgement
);
 
// Registers
reg[63:0] a_latched; // Latched 'a' input
reg[63:0] b_latched; // Latched 'b' input
reg[31:0] quotient_tmp; // Temporary result
reg[31:0] remainder_tmp; // Temporary result
reg negative_output; // If output is negative
reg[5:0] count; // Downward counter (32->0)
reg abp_last; // Level of last ABP request
reg[63:0] diff; // Difference
 
// Sequential logic
always @(posedge sys_clock_i) begin
 
// Initialization
if(sys_reset_i) begin
 
quotient_o = 0;
remainder_o = 0;
abp_ack_o = 0;
negative_output = 0;
count = 6'd0;
abp_last = 0;
 
// New request
end else if(abp_req_i!=abp_last) begin
 
abp_last = abp_req_i; // Latch level of ABP request
count = 6'd32; // Start counter
quotient_tmp = 0; // Initialize result
remainder_tmp = 0; // Initialize result
a_latched = (!signed_i || !a_i[31]) ? { 32'd0, a_i } : { 32'd0, (~a_i + 1'b1) };
b_latched = (!signed_i || !b_i[31]) ? { 1'b0, b_i, 31'd0 } : { 1'b0, ~b_i + 1'b1, 31'd0 };
negative_output = signed_i && (a_i[31] ^ b_i[31]);
quotient_o = (!negative_output) ? quotient_tmp : (~quotient_tmp+1); // Debugging only
remainder_o = (!negative_output) ? a_latched[31:0] : (~a_latched[31:0]+1); // Debugging only
// Calculating
end else if(count>0) begin
 
count = count-1;
diff = a_latched-b_latched;
quotient_tmp = quotient_tmp << 1;
if(!diff[63]) begin
a_latched = diff;
quotient_tmp[0] = 1;
end
b_latched = b_latched >> 1;
quotient_o = (!negative_output) ? quotient_tmp : (~quotient_tmp+1); // Debugging only
remainder_o = (!negative_output) ? a_latched[31:0] : (~a_latched[31:0]+1); // Debugging only
 
// Return the result
end else if(count==0) begin
 
abp_ack_o = abp_req_i; // Return the result
quotient_o = (!negative_output) ? quotient_tmp : (~quotient_tmp+1);
remainder_o = (!negative_output) ? a_latched[31:0] : (~a_latched[31:0]+1);
 
end
 
end
 
endmodule
 
/trunk/hdl/rtl/m1_core/m1_cpu.v
0,0 → 1,1917
/*
* Simply RISC M1 Central Processing Unit
*/
 
`include "m1_defs.vh"
 
module m1_cpu (
 
// System
input sys_clock_i, // System Clock
input sys_reset_i, // System Reset
input sys_irq_i, // Interrupt Request
 
// ALU
output[31:0] alu_a_o, // ALU Operand A
output[31:0] alu_b_o, // ALU Operand B
output[4:0] alu_func_o, // ALU Function
output alu_signed_o, // ALU operation is Signed
input[31:0] alu_result_i, // ALU Result
input alu_carry_i, // ALU Carry
 
// Multiplier
output reg mul_req_o, // Multiplier Request
output[31:0] mul_a_o, // Multiplier Operand A
output[31:0] mul_b_o, // Multiplier Operand B
output mul_signed_o, // Multiplication is Signed
input mul_ack_i, // Multiplier Ack
input[63:0] mul_product_i, // Multiplier Product
 
// Divider
output reg div_req_o, // Divider Request
output[31:0] div_a_o, // Divider Operand A
output[31:0] div_b_o, // Divider Operand B
output div_signed_o, // Division is Signed
input div_ack_i, // Divider Ack
input[31:0] div_quotient_i, // Divider Quotient
input[31:0] div_remainder_i, // Divider Remainder
 
// Instruction Memory
output imem_read_o, // I$ Read
output[31:0] imem_addr_o, // I$ Address
input imem_done_i, // I$ Done
input[31:0] imem_data_i, // I$ Data
 
// Data Memory
output dmem_read_o, // D$ Read
output dmem_write_o, // D$ Write
output[3:0] dmem_sel_o, // D$ Byte selector
output[31:0] dmem_addr_o, // D$ Address
output[31:0] dmem_data_o, // D$ Write Data
input dmem_done_i, // D$ Done
input[31:0] dmem_data_i // D$ Read Data
 
);
 
/*
* Registers
*/
 
// Register file
reg[31:0] GPR[31:0]; // General Purpose Registers
reg[31:0] PC; // Program Counter
reg[31:0] HI, LO; // HI and LO registers (for multiplication/division)
 
/*
* Pipeline latches
*/
 
// Latch 1: IF/ID
reg[31:0] if_id_opcode; // Instruction Register
reg[31:0] if_id_addr, if_id_addrnext; // Addresses of the fetched opcode and of the next one
 
// Latch 2: ID/EX
reg[31:0] id_ex_opcode;
reg[31:0] id_ex_addr, id_ex_addrnext;
reg[31:0] id_ex_addrbranch, id_ex_addrjump, id_ex_addrjr; // Evaluated jump addresses
reg[31:0] id_ex_alu_a, id_ex_alu_b; // ALU operands
reg[4:0] id_ex_alu_func; // ALU operation code
reg id_ex_alu_signed; // ALU operation is signed
reg id_ex_branch, id_ex_jump, id_ex_jr, id_ex_linked; // Instruction is a jump
reg id_ex_mult, id_ex_div; // Instruction is a multiplication/division
reg id_ex_load, id_ex_store; // Instruction is a load/store
reg[2:0] id_ex_size; // Load/store size (see defs.h)
reg[31:0] id_ex_store_value; // Store value
reg[4:0] id_ex_destreg; // Destination register (GPR number)
reg id_ex_desthi, id_ex_destlo; // Destination register (HI/LO)
 
// Latch 3: EX/MEM
reg[31:0] ex_mem_opcode;
reg[31:0] ex_mem_addr, ex_mem_addrnext;
reg[31:0] ex_mem_addrbranch, ex_mem_addrjump, ex_mem_addrjr;
reg[63:0] ex_mem_aluout; // ALU result
reg ex_mem_branch, ex_mem_jump, ex_mem_jr, ex_mem_linked;
reg ex_mem_mult, ex_mem_div;
reg ex_mem_load,ex_mem_store;
reg[31:0] ex_mem_store_value;
reg[3:0] ex_mem_store_sel; // Byte Selector on Stores
reg[4:0] ex_mem_destreg;
reg ex_mem_desthi, ex_mem_destlo;
 
// Latch 4: MEM/WB
reg[31:0] mem_wb_opcode;
reg[31:0] mem_wb_addr, mem_wb_addrnext;
reg[63:0] mem_wb_value; // Write-back value
reg[4:0] mem_wb_destreg;
reg mem_wb_desthi, mem_wb_destlo;
 
/*
* Combinational logic
*/
 
// ALU
assign alu_a_o = id_ex_alu_a;
assign alu_b_o = id_ex_alu_b;
assign alu_func_o = id_ex_alu_func;
assign alu_signed_o = id_ex_alu_signed;
 
// Multiplier
assign mul_a_o = id_ex_alu_a;
assign mul_b_o = id_ex_alu_b;
assign mul_signed_o = id_ex_alu_signed;
wire mul_ready = (mul_req_o==mul_ack_i); // Convert ABP ack to true/false format
wire mul_busy = !mul_ready;
 
// Divider
assign div_a_o = id_ex_alu_a;
assign div_b_o = id_ex_alu_b;
assign div_signed_o = id_ex_alu_signed;
wire div_ready = (div_req_o==div_ack_i); // Convert ABP ack to true/false format
wire div_busy = !div_ready;
 
// Incremented Program Counter
wire[31:0] PCnext = PC + 4;
 
// Instruction Memory
assign imem_read_o = 1;
assign imem_addr_o = PC;
 
// Data Memory
assign dmem_addr_o = ex_mem_aluout;
assign dmem_read_o = ex_mem_load;
assign dmem_write_o = ex_mem_store;
assign dmem_data_o = ex_mem_store_value;
assign dmem_sel_o = ex_mem_store_sel;
 
// Decode fields from the Instruction Register
wire[5:0] if_id_op = if_id_opcode[31:26]; // Operation code
wire[4:0] if_id_rs = if_id_opcode[25:21]; // Source register
wire[4:0] if_id_rt = if_id_opcode[20:16]; // Target register
wire[4:0] if_id_rd = if_id_opcode[15:11]; // Destination register
wire[31:0] if_id_imm_signext = {{16{if_id_opcode[15]}}, if_id_opcode[15:0]}; // Immediate field with sign-extension
wire[31:0] if_id_imm_zeroext = {16'b0, if_id_opcode[15:0]}; // Immediate field with zero-extension
wire[25:0] if_id_index = if_id_opcode[25:0]; // Index field
wire[4:0] if_id_shamt = if_id_opcode[10:6]; // Shift amount
wire[5:0] if_id_func = if_id_opcode[5:0]; // Function
 
// True for still undecoded operations that read GPR[rs]
wire if_id_reads_rs = (
if_id_op==`OPCODE_BEQ || if_id_op==`OPCODE_BNE || if_id_op==`OPCODE_BLEZ || if_id_op==`OPCODE_BGTZ ||
if_id_op==`OPCODE_ADDI || if_id_op==`OPCODE_ADDIU || if_id_op==`OPCODE_SLTI || if_id_op==`OPCODE_SLTIU ||
if_id_op==`OPCODE_ANDI || if_id_op==`OPCODE_ORI || if_id_op==`OPCODE_XORI || if_id_op==`OPCODE_LB ||
if_id_op==`OPCODE_LH || if_id_op==`OPCODE_LWL || if_id_op==`OPCODE_LW || if_id_op==`OPCODE_LBU ||
if_id_op==`OPCODE_LHU || if_id_op==`OPCODE_LWR || if_id_op==`OPCODE_SB || if_id_op==`OPCODE_SH ||
if_id_op==`OPCODE_SWL || if_id_op==`OPCODE_SW || if_id_op==`OPCODE_SWR || (
if_id_op==`OPCODE_SPECIAL && (
if_id_func==`FUNCTION_SLLV || if_id_func==`FUNCTION_SRLV || if_id_func==`FUNCTION_SRAV ||
if_id_func==`FUNCTION_JR || if_id_func==`FUNCTION_JALR || if_id_func==`FUNCTION_MTHI ||
if_id_func==`FUNCTION_MTLO || if_id_func==`FUNCTION_MULT || if_id_func==`FUNCTION_MULTU ||
if_id_func==`FUNCTION_DIV || if_id_func==`FUNCTION_DIVU || if_id_func==`FUNCTION_ADD ||
if_id_func==`FUNCTION_ADDU || if_id_func==`FUNCTION_SUB || if_id_func==`FUNCTION_SUBU ||
if_id_func==`FUNCTION_AND || if_id_func==`FUNCTION_OR || if_id_func==`FUNCTION_XOR ||
if_id_func==`FUNCTION_NOR || if_id_func==`FUNCTION_SLT || if_id_func==`FUNCTION_SLTU
)
) || (
if_id_op==`OPCODE_BCOND && (
if_id_rt==`BCOND_BLTZ || if_id_rt==`BCOND_BGEZ || if_id_rt==`BCOND_BLTZAL || if_id_rt==`BCOND_BGEZAL
)
)
);
 
// True for still undecoded operations that read GPR[rt]
wire if_id_reads_rt = (
if_id_op==`OPCODE_BEQ || if_id_op==`OPCODE_BNE || if_id_op==`OPCODE_SB || if_id_op==`OPCODE_SH ||
if_id_op==`OPCODE_SWL || if_id_op==`OPCODE_SW || if_id_op==`OPCODE_SWR || (
if_id_op==`OPCODE_SPECIAL && (
if_id_func==`FUNCTION_SLL || if_id_func==`FUNCTION_SRL || if_id_func==`FUNCTION_SRA ||
if_id_func==`FUNCTION_SLLV || if_id_func==`FUNCTION_SRLV || if_id_func==`FUNCTION_SRAV ||
if_id_func==`FUNCTION_MULT || if_id_func==`FUNCTION_MULTU || if_id_func==`FUNCTION_DIV ||
if_id_func==`FUNCTION_DIVU || if_id_func==`FUNCTION_ADD || if_id_func==`FUNCTION_ADDU ||
if_id_func==`FUNCTION_SUB || if_id_func==`FUNCTION_SUBU || if_id_func==`FUNCTION_AND ||
if_id_func==`FUNCTION_OR || if_id_func==`FUNCTION_XOR || if_id_func==`FUNCTION_NOR ||
if_id_func==`FUNCTION_SLT || if_id_func==`FUNCTION_SLTU
)
)
);
 
// True for still undecoded operations that read the HI register
wire if_id_reads_hi = (if_id_op==`OPCODE_SPECIAL && if_id_func==`FUNCTION_MFHI);
 
// True for still undecoded operations that read the LO register
wire if_id_reads_lo = (if_id_op==`OPCODE_SPECIAL && if_id_func==`FUNCTION_MFLO);
 
// Finally detect a RAW hazard
wire raw_detected = (
(if_id_reads_rs && if_id_rs!=0 &&
(if_id_rs==id_ex_destreg || if_id_rs==ex_mem_destreg || if_id_rs==mem_wb_destreg)) ||
(if_id_reads_rt && if_id_rt!=0 &&
(if_id_rt==id_ex_destreg || if_id_rt==ex_mem_destreg || if_id_rt==mem_wb_destreg)) ||
(if_id_reads_hi && (id_ex_desthi || ex_mem_desthi || mem_wb_desthi)) ||
(if_id_reads_lo && (id_ex_destlo || ex_mem_destlo || mem_wb_destlo))
);
 
// Stall signals for all the stages
wire if_stall, id_stall, ex_stall, mem_stall, wb_stall;
assign if_stall = id_stall || !imem_done_i;
assign id_stall = ex_stall || raw_detected;
assign ex_stall = mem_stall || mul_busy || div_busy;
assign mem_stall = wb_stall || ( (dmem_read_o||dmem_write_o) && !dmem_done_i);
assign wb_stall = 0;
 
// Index for GPR initialization
integer i;
 
/*
* Sequential logic
*/
 
always @ (posedge sys_clock_i) begin
 
// Initialize all the registers
if (sys_reset_i==1) begin
 
// GPRs initialization
for(i=0; i<=31; i=i+1) GPR[i] <= 32'h00000000;
 
// System registers
PC <= `BOOT_ADDRESS;
HI <= 0;
LO <= 0;
 
// Initialize ABP requests to instantiated modules
mul_req_o <= 0;
div_req_o <= 0;
 
// Latch 1: IF/ID
if_id_opcode <= `NOP;
if_id_addr <= `BOOT_ADDRESS;
if_id_addrnext <= 0;
 
// Latch 2: ID/EX
id_ex_opcode <= 0;
id_ex_addr <= 0;
id_ex_addrnext <= 0;
id_ex_addrjump <= 0;
id_ex_addrbranch <= 0;
id_ex_alu_a <= 0;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <=0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
 
ex_mem_opcode <= 0;
ex_mem_addr <= 0;
ex_mem_addrnext <= 0;
ex_mem_addrjump <= 0;
ex_mem_addrbranch <= 0;
ex_mem_aluout <= 0;
ex_mem_branch <= 0;
ex_mem_jump <= 0;
ex_mem_jr <= 0;
ex_mem_linked <= 0;
ex_mem_mult <= 0;
ex_mem_div <= 0;
ex_mem_load <= 0;
ex_mem_store <= 0;
ex_mem_store_value <= 0;
ex_mem_store_sel <= 0;
ex_mem_destreg <= 0;
ex_mem_desthi <= 0;
ex_mem_destlo <= 0;
 
// Latch 4: MEM/WB
mem_wb_opcode <= 0;
mem_wb_addr <= 0;
mem_wb_addrnext <= 0;
mem_wb_value <= 0;
mem_wb_destreg <= 0;
mem_wb_desthi <= 0;
mem_wb_destlo <= 0;
 
end else begin
 
$display("================> Time %t <================", $time);
 
/*
* Pipeline Stage 1: Instruction Fetch (IF)
*
* READ/WRITE:
* - read memory
* - write the IF/ID latch
* - write the PC register
*
* DESCRIPTION:
* This stage usually reads the next instruction from the PC address in memory and
* then updates the PC value by incrementing it by 4.
* When a hazard is detected this stage is idle.
*/
 
// A RAW hazard will stall the CPU
if(if_stall) begin
 
if(id_stall) begin
$display("INFO: CPU(%m)-IF: Fetching stalled and latch kept for following stalled pipeline stage");
end else begin
$display("INFO: CPU(%m)-IF: Fetching stalled and bubble inserted for following running pipeline stage");
if_id_opcode <= `BUBBLE;
end
 
end else begin
 
// Branch taken: insert a bubble and increment PC
if(ex_mem_branch==1 && ex_mem_aluout==32'h00000001) begin
 
$display("INFO: CPU(%m)-IF: Bubble inserted due branch taken in EX/MEM instruction @ADDR=%X w/OPCODE=%X having ALUout=%X", ex_mem_addr, ex_mem_opcode, ex_mem_aluout);
if_id_opcode <= `BUBBLE;
PC <= ex_mem_addrbranch;
 
//Jump to the required immediate address
end else if(id_ex_jump==1) begin
 
$display("INFO: CPU(%m)-IF: Bubble inserted due to jump in ID/EX instruction @ADDR=%X w/OPCODE=%X", id_ex_addr, id_ex_opcode);
if_id_opcode <= `BUBBLE;
PC <= id_ex_addrjump;
// Jump to the required address stored in GPR
end else if(id_ex_jr==1) begin
 
$display("INFO: CPU(%m)-IF: Bubble inserted due to jump register in ID/EX instruction @ADDR=%X w/OPCODE=%X", id_ex_addr, id_ex_opcode);
if_id_opcode <= `BUBBLE;
PC <= id_ex_addrjr;
// Normal execution
end else begin
 
$display("INFO: CPU(%m)-IF: Fetched from Program Counter @ADDR=%h getting OPCODE=%X", PC, imem_data_i);
if_id_opcode <= imem_data_i;
if_id_addr <= PC;
if_id_addrnext <= PCnext;
PC <= PCnext;
 
end
end
 
/*
* Pipeline Stage 2: Instruction Decode (ID)
*
* READ/WRITE:
* - read the IF/ID latch
* - read the register file
* - write the ID/EX latch
*
* DESCRIPTION:
* This stage decodes the instruction and puts the values for the ALU inputs
*/
 
if(id_stall) begin
if(ex_stall) begin
$display("INFO: CPU(%m)-ID: Decoding stalled and latch kept for following stalled pipeline stage");
end else begin
$display("INFO: CPU(%m)-ID: Decoding stalled and bubble inserted for following running pipeline stage");
id_ex_opcode <=`BUBBLE;
id_ex_alu_a <= 0;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_addr <= if_id_addr;
id_ex_addrnext <= 0;
id_ex_addrjump <= 0;
id_ex_addrbranch <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
end else begin
id_ex_opcode <= if_id_opcode;
id_ex_addr <= if_id_addr;
id_ex_addrnext <= if_id_addrnext;
id_ex_addrbranch <= if_id_addrnext + {if_id_imm_signext[29:0], 2'b00};
id_ex_addrjump <= {if_id_addr[31:28], if_id_index, 2'b00};
id_ex_addrjr <= GPR[if_id_rs];
 
if(if_id_opcode==`BUBBLE) begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BUBBLE", if_id_addr, if_id_opcode);
id_ex_alu_a <= 0;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end else case(if_id_op)
`OPCODE_J:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as J %h", if_id_addr, if_id_opcode, if_id_index);
id_ex_alu_a <= 0;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 1;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_JAL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as JAL %h", if_id_addr, if_id_opcode, if_id_index);
id_ex_alu_a <= if_id_addrnext;
id_ex_alu_b <= 4;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 1;
id_ex_jr <= 0;
id_ex_linked <= 1;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 31;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_BEQ:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BEQ r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_rt, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_SEQ;
id_ex_alu_signed <= 0;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_BNE:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BNE r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_rt, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_SNE;
id_ex_alu_signed <= 0;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_BLEZ:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BLEZ r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_SLE;
id_ex_alu_signed <= 0;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_BGTZ:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BGTZ r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_SGT;
id_ex_alu_signed <= 0;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_ADDI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as ADDI r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_ADDIU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as ADDIU r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SLTI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SLTI r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_SLT;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SLTIU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SLTIU r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_SLT;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_ANDI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as ANDI r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_zeroext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_zeroext;
id_ex_alu_func <= `ALU_OP_AND;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_ORI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as ORI r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_zeroext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_zeroext;
id_ex_alu_func <= `ALU_OP_OR;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_XORI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as XORI r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_rs, if_id_imm_zeroext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_zeroext;
id_ex_alu_func <= `ALU_OP_XOR;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LUI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LUI r%d, %h", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_zeroext);
id_ex_alu_a <= if_id_imm_zeroext;
id_ex_alu_b <= 16;
id_ex_alu_func <= `ALU_OP_SLL;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_COP0:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as COP0", if_id_addr, if_id_opcode);
end
`OPCODE_COP1:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as COP1", if_id_addr, if_id_opcode);
end
`OPCODE_COP2:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as COP2", if_id_addr, if_id_opcode);
end
`OPCODE_COP3:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as COP3", if_id_addr, if_id_opcode);
end
`OPCODE_LB:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LB r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_BYTE;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LH:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LH r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_HALF;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LWL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LWL r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_LEFT;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LW:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LW r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_WORD;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LBU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LBU r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_BYTE;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LHU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LHU r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_HALF;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LWR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LWR r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 1;
id_ex_store <= 0;
id_ex_size <= `SIZE_RIGHT;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rt;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SB:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SB r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 1;
id_ex_size <= `SIZE_BYTE;
id_ex_store_value <= GPR[if_id_rt];
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SH:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SH r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 1;
id_ex_size <= `SIZE_HALF;
id_ex_store_value <= GPR[if_id_rt];
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SWL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SWL r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 1;
id_ex_size <= `SIZE_LEFT;
id_ex_store_value <= GPR[if_id_rt];
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SW:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SW r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 1;
id_ex_size <= `SIZE_WORD;
id_ex_store_value <= GPR[if_id_rt];
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_SWR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SWR r%d, %d(r%d)", if_id_addr, if_id_opcode, if_id_rt, if_id_imm_signext, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= if_id_imm_signext;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 1;
id_ex_size <= `SIZE_RIGHT;
id_ex_store_value <= GPR[if_id_rt];
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`OPCODE_LWC1:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LWC1", if_id_addr, if_id_opcode);
end
`OPCODE_LWC2:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LWC2", if_id_addr, if_id_opcode);
end
`OPCODE_LWC3:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as LWC3", if_id_addr, if_id_opcode);
end
`OPCODE_SWC1:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SWC1", if_id_addr, if_id_opcode);
end
`OPCODE_SWC2:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SWC2", if_id_addr, if_id_opcode);
end
`OPCODE_SWC3:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SWC3", if_id_addr, if_id_opcode);
end
`OPCODE_SPECIAL:
case(if_id_func)
`FUNCTION_SLL:
begin
if(if_id_opcode==`NOP) $display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as NOP", if_id_addr, if_id_opcode);
else $display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SLL r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rd, if_id_rt, if_id_shamt);
id_ex_alu_a <= GPR[if_id_rt];
id_ex_alu_b <= if_id_shamt;
id_ex_alu_func <= `ALU_OP_SLL;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SRL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SRL r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rd, if_id_rt, if_id_shamt);
id_ex_alu_a <= GPR[if_id_rt];
id_ex_alu_b <= if_id_shamt;
id_ex_alu_func <= `ALU_OP_SRL;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SRA:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SRA r%d, r%d, %h", if_id_addr, if_id_opcode, if_id_rd, if_id_rt, if_id_shamt);
id_ex_alu_a <= GPR[if_id_rt];
id_ex_alu_b <= if_id_shamt;
id_ex_alu_func <= `ALU_OP_SRA;
id_ex_alu_signed <= 1; // does nothing??
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SLLV:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SLLV r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rt, if_id_rs);
id_ex_alu_a <= GPR[if_id_rt];
id_ex_alu_b <= GPR[if_id_rs];
id_ex_alu_func <= `ALU_OP_SLL;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SRLV:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SRLV r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rt, if_id_rs);
id_ex_alu_a <= GPR[if_id_rt];
id_ex_alu_b <= GPR[if_id_rs];
id_ex_alu_func <= `ALU_OP_SRL;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SRAV:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SRAV r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rt, if_id_rs);
id_ex_alu_a <= GPR[if_id_rt];
id_ex_alu_b <= GPR[if_id_rs];
id_ex_alu_func <= `ALU_OP_SRA;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_JR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as JR r%d", if_id_addr, if_id_opcode, if_id_rs);
id_ex_alu_a <= 0;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 1;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_JALR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as JALR [r%d,] r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs);
id_ex_alu_a <= if_id_addrnext;
id_ex_alu_b <= 4;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 1;
id_ex_linked <= 1;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SYSCALL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SYSCALL", if_id_addr, if_id_opcode);
// id_ex_alu_a <= 0;
// id_ex_alu_b <= 0;
// id_ex_alu_func <= `ALU_OP_ADD;
// id_ex_alu_signed <= 0;
// id_ex_branch <= 0;
// id_ex_jump <= 0;
// id_ex_jr <= 0;
// id_ex_linked <= 0;
// id_ex_mult <= 0;
// id_ex_div <= 0;
// id_ex_load <= 0;
// id_ex_store <= 0;
// id_ex_size <= 0;
// id_ex_store_value <= 0;
// id_ex_destreg <= 0;
// id_ex_desthi <= 0;
// id_ex_destlo <= 0;
end
`FUNCTION_BREAK:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BREAK", if_id_addr, if_id_opcode);
// id_ex_alu_a <= 0;
// id_ex_alu_b <= 0;
// id_ex_alu_func <= `ALU_OP_ADD;
// id_ex_alu_signed <= 0;
// id_ex_branch <= 0;
// id_ex_jump <= 0;
// id_ex_jr <= 0;
// id_ex_linked <= 0;
// id_ex_mult <= 0;
// id_ex_div <= 0;
// id_ex_load <= 0;
// id_ex_store <= 0;
// id_ex_size <= 0;
// id_ex_store_value <= 0;
// id_ex_destreg <= 0;
// id_ex_desthi <= 0;
// id_ex_destlo <= 0;
end
`FUNCTION_MFHI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as MFHI r%d", if_id_addr, if_id_opcode, if_id_rd);
id_ex_alu_a <= HI;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_MTHI:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as MTHI r%d", if_id_addr, if_id_opcode, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 1;
id_ex_destlo <= 0;
end
`FUNCTION_MFLO:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as MFLO r%d", if_id_addr, if_id_opcode, if_id_rd);
id_ex_alu_a <= LO;
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_MTLO:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as MTLO r%d", if_id_addr, if_id_opcode, if_id_rs);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 0;
id_ex_destlo <= 1;
end
`FUNCTION_MULT:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as MULT r%d, r%d", if_id_addr, if_id_opcode, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_MULT;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 1;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 1;
id_ex_destlo <= 1;
mul_req_o <= !mul_req_o; // Toggle the ABP request
end
`FUNCTION_MULTU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as MULTU r%d, r%d", if_id_addr, if_id_opcode, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_MULT;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 1;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 1;
id_ex_destlo <= 1;
mul_req_o <= !mul_req_o; // Toggle the ABP request
end
`FUNCTION_DIV:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as DIV r%d, r%d", if_id_addr, if_id_opcode, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_DIV;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 1;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 1;
id_ex_destlo <= 1;
div_req_o <= !div_req_o; // Toggle the ABP request
end
`FUNCTION_DIVU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as DIVU r%d, r%d", if_id_addr, if_id_opcode, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_DIV;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 1;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 0;
id_ex_desthi <= 1;
id_ex_destlo <= 1;
div_req_o <= !div_req_o; // Toggle the ABP request
end
`FUNCTION_ADD:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as ADD r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_ADDU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as ADDU r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_ADD;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SUB:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SUB r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_SUB;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SUBU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SUBU r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_SUB;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_AND:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as AND r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_AND;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_OR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as OR r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_OR;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_XOR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as XOR r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_XOR;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_NOR:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as NOR r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_NOR;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SLT:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SLT r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_SLT;
id_ex_alu_signed <= 1;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`FUNCTION_SLTU:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as SLTU r%d, r%d, r%d", if_id_addr, if_id_opcode, if_id_rd, if_id_rs, if_id_rt);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= GPR[if_id_rt];
id_ex_alu_func <= `ALU_OP_SLT;
id_ex_alu_signed <= 0;
id_ex_branch <= 0;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
endcase
`OPCODE_BCOND:
case(if_id_rt)
`BCOND_BLTZ:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BLTZ r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_SLT;
id_ex_alu_signed <= 1;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`BCOND_BGEZ:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BGEZ r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_SGE;
id_ex_alu_signed <= 1;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 0;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= if_id_rd;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`BCOND_BLTZAL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BLTZAL r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <= `ALU_OP_SLT;
id_ex_alu_signed <= 1;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 1;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 31;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
`BCOND_BGEZAL:
begin
$display("INFO: CPU(%m)-ID: Decoded instruction @ADDR=%X w/OPCODE=%X as BGEZAL r%d, %h", if_id_addr, if_id_opcode, if_id_rs, if_id_imm_signext);
id_ex_alu_a <= GPR[if_id_rs];
id_ex_alu_b <= 0;
id_ex_alu_func <=`ALU_OP_SGE;
id_ex_alu_signed <= 1;
id_ex_branch <= 1;
id_ex_jump <= 0;
id_ex_jr <= 0;
id_ex_linked <= 1;
id_ex_mult <= 0;
id_ex_div <= 0;
id_ex_load <= 0;
id_ex_store <= 0;
id_ex_size <= 0;
id_ex_store_value <= 0;
id_ex_destreg <= 31;
id_ex_desthi <= 0;
id_ex_destlo <= 0;
end
endcase
 
endcase
 
end
 
/*
* Pipeline Stage 3: Execute (EX)
*
* READ/WRITE:
* - read the ID/EX latch
* - write the EX/MEM latch
*
* DESCRIPTION:
* This stage takes the result from the ALU and put it in the proper latch.
* Please note that assignments to ALU inputs are done outside since they're wires.
*/
 
if(ex_stall) begin
if(mem_stall) begin
$display("INFO: CPU(%m)-EX: Execution stalled and latch kept for following stalled pipeline stage");
end else begin
$display("INFO: CPU(%m)-EX: Execution stalled and bubble inserted for following running pipeline stage");
ex_mem_opcode <= `BUBBLE;
ex_mem_addr <= id_ex_addr;
ex_mem_addrnext <= 0;
ex_mem_destreg <= 0;
ex_mem_desthi <= 0;
ex_mem_destlo <= 0;
end
 
end else begin
// If not stalled propagate values to next latches
ex_mem_opcode <= id_ex_opcode;
ex_mem_addr <= id_ex_addr;
ex_mem_addrnext <= id_ex_addrnext;
ex_mem_addrjump <= id_ex_addrjump;
ex_mem_addrbranch <= id_ex_addrbranch;
ex_mem_branch <= id_ex_branch;
ex_mem_jump <= id_ex_jump;
ex_mem_jr <= id_ex_jr;
ex_mem_linked <= id_ex_linked;
ex_mem_mult <= id_ex_mult;
ex_mem_div <= id_ex_div;
ex_mem_load <= id_ex_load;
ex_mem_store <= id_ex_store;
ex_mem_destreg <= id_ex_destreg;
ex_mem_desthi <= id_ex_desthi;
ex_mem_destlo <= id_ex_destlo;
 
// Choose the output from ALU, Multiplier or Divider
if(id_ex_mult) ex_mem_aluout <= mul_product_i;
else if(id_ex_div) ex_mem_aluout <= { div_remainder_i, div_quotient_i };
else ex_mem_aluout <= alu_result_i;
 
if(id_ex_store) begin
 
$display("INFO: CPU(%m)-EX: Execution of Store instruction @ADDR=%X w/OPCODE=%X started to STORE_ADDR=%X w/STORE_DATA=%X", id_ex_addr, id_ex_opcode, alu_result_i, id_ex_store_value);
case(id_ex_size)
`SIZE_WORD: begin
ex_mem_store_value <= id_ex_store_value;
ex_mem_store_sel <= 4'b1111;
end
`SIZE_HALF: begin
if(alu_result_i[1]==0) begin
ex_mem_store_value <= {{16'b0},id_ex_store_value[15:0]};
ex_mem_store_sel <= 4'b0011;
end else begin
ex_mem_store_value <= {id_ex_store_value[15:0],{16'b0}};
ex_mem_store_sel <= 4'b1100;
end
end
`SIZE_BYTE: begin
case(alu_result_i[1:0])
2'b00: begin
ex_mem_store_value <= {{24'b0},id_ex_store_value[7:0]};
ex_mem_store_sel <= 4'b0001;
end
2'b01: begin
ex_mem_store_value <= {{16'b0},id_ex_store_value[7:0],{8'b0}};
ex_mem_store_sel <= 4'b0010;
end
2'b10: begin
ex_mem_store_value <= {{8'b0},id_ex_store_value[7:0],{16'b0}};
ex_mem_store_sel <= 4'b0100;
end
2'b11: begin
ex_mem_store_value <= {id_ex_store_value[7:0],{24'b0}};
ex_mem_store_sel <= 4'b1000;
end
endcase
end
endcase
 
end else begin
 
// Not a store
$display("INFO: CPU(%m)-EX: Execution of instruction @ADDR=%X w/OPCODE=%X gave ALU result %X", id_ex_addr, id_ex_opcode, alu_result_i);
 
end
 
end
 
/*
* Pipeline Stage 4: Memory access (MEM)
*
* READ/WRITE:
* - read the EX/MEM latch
* - read or write memory
* - write the MEM/WB latch
*
* DESCRIPTION:
* This stage perform accesses to memory to read/write the data during
* the load/store operations.
*/
 
if(mem_stall) begin
 
$display("INFO: CPU(%m)-MEM: Memory stalled");
 
end else begin
 
mem_wb_opcode <= ex_mem_opcode;
mem_wb_addr <= ex_mem_addr;
mem_wb_addrnext <= ex_mem_addrnext;
mem_wb_destreg <= ex_mem_destreg;
mem_wb_desthi <= ex_mem_desthi;
mem_wb_destlo <= ex_mem_destlo;
 
if(ex_mem_load) begin
 
$display("INFO: CPU(%m)-MEM: Loading value %X", dmem_data_i);
mem_wb_value[63:32] <= 32'b0;
mem_wb_value[31:0] <= dmem_data_i;
 
end else if (ex_mem_desthi && ex_mem_destlo) begin
 
$display("INFO: CPU(%m)-MEM: Propagating value %X", ex_mem_aluout);
mem_wb_value[31:0] <= ex_mem_aluout[31:0];
mem_wb_value[63:32] <= ex_mem_aluout[63:32];
 
end else if (ex_mem_desthi) begin
 
$display("INFO: CPU(%m)-MEM: Propagating value %X", ex_mem_aluout);
mem_wb_value[63:32] <= ex_mem_aluout[31:0];
mem_wb_value[31:0] <= 32'b0;
 
end else begin
 
$display("INFO: CPU(%m)-MEM: Propagating value %X", ex_mem_aluout);
mem_wb_value[31:0] <= ex_mem_aluout[31:0];
mem_wb_value[63:32] <= 32'b0;
 
end
 
end
 
/*
* Pipeline Stage 5: Write Back (WB)
*
* READ/WRITE:
* - read the MEM/WB latch
* - write the register file
*
* DESCRIPTION:
* This stage writes back the result into the proper register (GPR, HI, LO).
*/
 
if(wb_stall) begin
 
$display("INFO: CPU(%m)-WB: Write-Back stalled");
 
end else begin
 
// GPRs
if(mem_wb_destreg!=0) begin
$display("INFO: CPU(%m)-WB: Writing Back GPR[%d]=%X", mem_wb_destreg, mem_wb_value[31:0]);
GPR[mem_wb_destreg] <= mem_wb_value[31:0];
end
 
// HI
if(mem_wb_desthi) begin
$display("INFO: CPU(%m)-WB: Writing Back HI=%X", mem_wb_value[63:32]);
HI <= mem_wb_value[63:32];
end
 
// LO
if(mem_wb_destlo) begin
$display("INFO: CPU(%m)-WB: Writing Back LO=%X", mem_wb_value[31:0]);
LO <= mem_wb_value[31:0];
end
 
// Idle
if(mem_wb_destreg==0 & mem_wb_desthi==0 & mem_wb_destlo==0)
$display("INFO: CPU(%m)-WB: Write-Back has nothing to do");
 
end
 
// Display register file at each raising edge
$display("INFO: CPU(%m)-Regs: R00=%X R01=%X R02=%X R03=%X R04=%X R05=%X R06=%X R07=%X",
GPR[0], GPR[1], GPR[2], GPR[3], GPR[4], GPR[5], GPR[6], GPR[7]);
$display("INFO: CPU(%m)-Regs: R08=%X R09=%X R10=%X R11=%X R12=%X R13=%X R14=%X R15=%X",
GPR[8], GPR[9], GPR[10], GPR[11], GPR[12], GPR[13], GPR[14], GPR[15]);
$display("INFO: CPU(%m)-Regs: R16=%X R17=%X R18=%X R19=%X R20=%X R21=%X R22=%X R23=%X",
GPR[16], GPR[17], GPR[18], GPR[19], GPR[20], GPR[21], GPR[22], GPR[23]);
$display("INFO: CPU(%m)-Regs: R24=%X R25=%X R26=%X R27=%X R28=%X R29=%X R30=%X R31=%X",
GPR[24], GPR[25], GPR[26], GPR[27], GPR[28], GPR[29], GPR[30], GPR[31]);
$display("INFO: CPU(%m)-Regs: PC=%X HI=%X LO=%X",
PC, HI, LO);
 
end
end
 
endmodule
 
/trunk/hdl/rtl/m1_core/m1_core.v
1,25 → 1,196
/*
* Simply RISC M1 Core Top-Level
*
* Schematic with instances of CPU, ALU, Mul, Div and MMU
*/
 
module m1_core (
sys_clock_i, sys_reset_i, sys_irq_i
 
// System
input sys_clock_i, // System clock
input sys_reset_i, // System reset
input sys_irq_i, // Interrupt Request
 
// Wishbone master interface
output wb_cyc_o, // WB Cycle
output wb_stb_o, // WB Strobe
output wb_we_o, // WB Write Enable
output[31:0] wb_adr_o, // WB Address
output[31:0] wb_dat_o, // WB Data Out
output[3:0] wb_sel_o, // WB Byte Select
input wb_ack_i, // WB Ack
input[31:0] wb_dat_i // WB Data In
 
);
input sys_clock_i, sys_reset_i;
input[31:0] sys_irq_i;
wire[31:0] imem_addr, imem_data, dmem_addr, dmem_rdata, dmem_wdata;
wire imem_read, imem_busy, dmem_read, dmem_write, dmem_busy;
/*
* Wires
*/
 
// ALU
wire[31:0] alu_a;
wire[31:0] alu_b;
wire[4:0] alu_func;
wire alu_signed;
wire[31:0] alu_result;
wire alu_carry;
 
// Multiplier
wire mul_req;
wire[31:0] mul_a;
wire[31:0] mul_b;
wire mul_signed;
wire mul_ack;
wire[63:0] mul_product;
 
// Divider
wire div_req;
wire[31:0] div_a;
wire[31:0] div_b;
wire div_signed;
wire div_ack;
wire[31:0] div_quotient;
wire[31:0] div_remainder;
 
// Instruction Memory
wire imem_read;
wire[31:0] imem_addr;
wire imem_done;
wire[31:0] imem_data;
 
// Data Memory
wire dmem_read;
wire dmem_write;
wire[31:0] dmem_addr;
wire[31:0] dmem_data_w;
wire[3:0] dmem_sel;
wire dmem_done;
wire[31:0] dmem_data_r;
 
m1_cpu cpu_0(sys_clock_i, sys_reset_i, sys_irq_i,
imem_addr, imem_data, imem_read, imem_busy,
dmem_addr, dmem_rdata, dmem_wdata, dmem_read, dmem_write, dmem_busy , dmem_sel
/*
* Module instances
*/
 
// CPU
m1_cpu m1_cpu_0 (
 
// System
.sys_clock_i(sys_clock_i),
.sys_reset_i(sys_reset_i),
.sys_irq_i(sys_irq_i),
 
// ALU
.alu_a_o(alu_a),
.alu_b_o(alu_b),
.alu_func_o(alu_func),
.alu_signed_o(alu_signed),
.alu_result_i(alu_result),
.alu_carry_i(alu_carry),
 
// Multiplier
.mul_req_o(mul_req),
.mul_a_o(mul_a),
.mul_b_o(mul_b),
.mul_signed_o(mul_signed),
.mul_ack_i(mul_ack),
.mul_product_i(mul_product),
 
// Divider
.div_req_o(div_req),
.div_a_o(div_a),
.div_b_o(div_b),
.div_signed_o(div_signed),
.div_ack_i(div_ack),
.div_quotient_i(div_quotient),
.div_remainder_i(div_remainder),
 
// Instruction Memory
.imem_read_o(imem_read),
.imem_addr_o(imem_addr),
.imem_data_i(imem_data),
.imem_done_i(imem_done),
 
// Data Memory
.dmem_read_o(dmem_read),
.dmem_write_o(dmem_write),
.dmem_sel_o(dmem_sel),
.dmem_addr_o(dmem_addr),
.dmem_data_o(dmem_data_w),
.dmem_data_i(dmem_data_r),
.dmem_done_i(dmem_done)
 
);
 
m1_mmu mmu_0(sys_clock_i, sys_reset_i,
imem_addr, imem_data, imem_read, imem_busy,
dmem_addr, dmem_rdata, dmem_wdata, dmem_read, dmem_write, dmem_busy , dmem_sel
// ALU
m1_alu m1_alu_0 (
.a_i(alu_a),
.b_i(alu_b),
.func_i(alu_func),
.signed_i(alu_signed),
.result_o(alu_result),
.carry_o(alu_carry)
);
 
// Multiplier
m1_mul m1_mul_0 (
.sys_reset_i(sys_reset_i),
.sys_clock_i(sys_clock_i),
 
.abp_req_i(mul_req),
.a_i(mul_a),
.b_i(mul_b),
.signed_i(mul_signed),
.abp_ack_o(mul_ack),
.product_o(mul_product)
);
 
// Divider
m1_div m1_div_0 (
.sys_reset_i(sys_reset_i),
.sys_clock_i(sys_clock_i),
 
.abp_req_i(div_req),
.a_i(div_a),
.b_i(div_b),
.signed_i(div_signed),
.abp_ack_o(div_ack),
.quotient_o(div_quotient),
.remainder_o(div_remainder)
);
 
// MMU
m1_mmu m1_mmu_0 (
 
// System
.sys_clock_i(sys_clock_i),
.sys_reset_i(sys_reset_i),
 
// Instruction Memory
.imem_read_i(imem_read),
.imem_addr_i(imem_addr),
.imem_data_o(imem_data),
.imem_done_o(imem_done),
 
// Data Memory
.dmem_read_i(dmem_read),
.dmem_write_i(dmem_write),
.dmem_sel_i(dmem_sel),
.dmem_addr_i(dmem_addr),
.dmem_data_i(dmem_data_w),
.dmem_data_o(dmem_data_r),
.dmem_done_o(dmem_done),
 
// Wishbone master interface
.wb_cyc_o(wb_cyc_o),
.wb_stb_o(wb_stb_o),
.wb_we_o(wb_we_o),
.wb_adr_o(wb_adr_o),
.wb_dat_o(wb_dat_o),
.wb_sel_o(wb_sel_o),
.wb_ack_i(wb_ack_i),
.wb_dat_i(wb_dat_i)
 
);
 
endmodule
 
/trunk/hdl/rtl/m1_core/m1_defs.vh
0,0 → 1,119
/*
* Simply RISC M1 Defines
*/
 
// Useful constants
`define NOP 32'h00000000
`define BUBBLE 32'hFFFFFFFF
`define BOOT_ADDRESS 32'h00000000 /* could be 32'hBFC00000 */
`define STACK_TOP 32'h00000FF0 /* for 4 KBytes Internal SRAM */
 
// Load/Store size
`define SIZE_BYTE 3'b000
`define SIZE_HALF 3'b001
`define SIZE_WORD 3'b011
`define SIZE_LEFT 3'b100
`define SIZE_RIGHT 3'b101
 
// Opcodes (ordered by binary value)
`define OPCODE_SPECIAL 6'b000000 // SPECIAL instruction class
`define OPCODE_BCOND 6'b000001 // BCOND instruction class
`define OPCODE_J 6'b000010 // Jump
`define OPCODE_JAL 6'b000011 // Jump and link
`define OPCODE_BEQ 6'b000100 // Branch on equal
`define OPCODE_BNE 6'b000101 // Branch on not equal
`define OPCODE_BLEZ 6'b000110 // Branch on less than or equal to zero
`define OPCODE_BGTZ 6'b000111 // Branch on greater than zero
`define OPCODE_ADDI 6'b001000 // Add immediate
`define OPCODE_ADDIU 6'b001001 // Add immediate unsigned
`define OPCODE_SLTI 6'b001010 // Set on less than immediate
`define OPCODE_SLTIU 6'b001011 // Set on less than immediate unsigned
`define OPCODE_ANDI 6'b001100 // Bitwise AND immediate
`define OPCODE_ORI 6'b001101 // Bitwise OR immediate
`define OPCODE_XORI 6'b001110 // Bitwise XOR immediate
`define OPCODE_LUI 6'b001111 // Load upper immediate
`define OPCODE_COP0 6'b010000 // Coprocessor 0 Operation TODO
`define OPCODE_COP1 6'b010001 // Coprocessor 1 Operation (optional)
`define OPCODE_COP2 6'b010010 // Coprocessor 2 Operation (optional)
`define OPCODE_COP3 6'b010011 // Coprocessor 3 Operation (optional)
`define OPCODE_LB 6'b100000 // Load byte
`define OPCODE_LH 6'b100001 // Load halfword
`define OPCODE_LWL 6'b100010 // Load word left TODO
`define OPCODE_LW 6'b100011 // Load word
`define OPCODE_LBU 6'b100100 // Load byte unsigned
`define OPCODE_LHU 6'b100101 // Load halfword unsigned
`define OPCODE_LWR 6'b100110 // Load word right TODO
`define OPCODE_SB 6'b101000 // Store byte
`define OPCODE_SH 6'b101001 // Store halfword
`define OPCODE_SWL 6'b101010 // Store word left TODO
`define OPCODE_SW 6'b101011 // Store word
`define OPCODE_SWR 6'b101110 // Store word right TODO
`define OPCODE_LWC1 6'b110001 // Load word to Coprocessor 1 (optional)
`define OPCODE_LWC2 6'b110010 // Load word to Coprocessor 2 (optional)
`define OPCODE_LWC3 6'b110011 // Load word to Coprocessor 3 (optional)
`define OPCODE_SWC1 6'b111001 // Store word from Coprocessor 1 (optional)
`define OPCODE_SWC2 6'b111010 // Store word from Coprocessor 2 (optional)
`define OPCODE_SWC3 6'b111011 // Store word from Coprocessor 3 (optional)
 
// SPECIAL instruction class functions (ordered by binary value)
`define FUNCTION_SLL 6'b000000 // Shift left logical
`define FUNCTION_SRL 6'b000010 // Shift right logical
`define FUNCTION_SRA 6'b000011 // Shift right arithmetic
`define FUNCTION_SLLV 6'b000100 // Shift left logical variable
`define FUNCTION_SRLV 6'b000110 // Shift right logical variable
`define FUNCTION_SRAV 6'b000111 // Shift right arithmetic variable
`define FUNCTION_JR 6'b001000 // Jump register
`define FUNCTION_JALR 6'b001001 // Jump and link register
`define FUNCTION_SYSCALL 6'b001100 // System call TODO
`define FUNCTION_BREAK 6'b001101 // Breakpoint TODO
`define FUNCTION_MFHI 6'b010000 // Move from HI register TODO
`define FUNCTION_MTHI 6'b010001 // Move to HI register TODO
`define FUNCTION_MFLO 6'b010010 // Move from LO register TODO
`define FUNCTION_MTLO 6'b010011 // Move to LO register TODO
`define FUNCTION_MULT 6'b011000 // Multiply TODO
`define FUNCTION_MULTU 6'b011001 // Multiply unsigned TODO
`define FUNCTION_DIV 6'b011010 // Divide TODO
`define FUNCTION_DIVU 6'b011011 // Divide unsigned TODO
`define FUNCTION_ADD 6'b100000 // Add
`define FUNCTION_ADDU 6'b100001 // Add unsigned
`define FUNCTION_SUB 6'b100010 // Subtract
`define FUNCTION_SUBU 6'b100011 // Subtract unsigned
`define FUNCTION_AND 6'b100100 // Bitwise AND
`define FUNCTION_OR 6'b100101 // Bitwise OR
`define FUNCTION_XOR 6'b100110 // Bitwise XOR
`define FUNCTION_NOR 6'b100111 // Bitwise NOR
`define FUNCTION_SLT 6'b101010 // Set on less than
`define FUNCTION_SLTU 6'b101011 // Set on less than unsigned
 
// BCOND instruction class rt fields (ordered by binary value)
`define BCOND_BLTZ 5'b00000 // Branch on less than zero
`define BCOND_BGEZ 5'b00001 // Branch on greater than or equal to zero
`define BCOND_BLTZAL 5'b10000 // Branch on less than zero and link
`define BCOND_BGEZAL 5'b10001 // Branch on greater than or equal to zero and link
 
// Coprocessors instruction class rs fields (ordered by binary value)
`define COP_MFCz 5'b00000 // Move from Coprocessor z
`define COP_CFCz 5'b00010 // Copy from Coprocessor z
`define COP_MTCz 5'b00100 // Move to Coprocessor z
`define COP_CTCz 5'b00110 // Copy to Coprocessor z
`define COP_BCOND 5'b01000 // Branch condition for Coprocessor z
 
// ALU operation codes used internally (please note that signed/unsigned is another input)
`define ALU_OP_SLL 5'b00001
`define ALU_OP_SRL 5'b00010
`define ALU_OP_SRA 5'b00011
`define ALU_OP_ADD 5'b00100
`define ALU_OP_SUB 5'b00101
`define ALU_OP_AND 5'b00110
`define ALU_OP_OR 5'b00111
`define ALU_OP_XOR 5'b01000
`define ALU_OP_NOR 5'b01001
`define ALU_OP_SEQ 5'b01010
`define ALU_OP_SNE 5'b01011
`define ALU_OP_SLT 5'b01100
`define ALU_OP_SLE 5'b01101
`define ALU_OP_SGT 5'b01110
`define ALU_OP_SGE 5'b01111
`define ALU_OP_MULT 5'b10000
`define ALU_OP_DIV 5'b10001
 
/trunk/hdl/rtl/m1_core/m1_mul.v
0,0 → 1,71
/*
* Simply RISC M1 Multiplier
*
* Simple RTL-level Multiplier with Alternating Bit Protocol (ABP) interface.
*/
 
// 32-bit * 32-bit Integer Multiplier (this version is not optimized and always takes 32 cycles)
module m1_mul(
input sys_reset_i, // System Reset
input sys_clock_i, // System Clock
input[31:0] a_i, // Operand A
input[31:0] b_i, // Operand B
input signed_i, // If multiplication is signed
output reg[63:0] product_o, // Product of multiplication
input abp_req_i, // ABP Request
output reg abp_ack_o // ABP Acknowledgement
);
 
 
// Registers
reg[63:0] a_latched; // Latched 'a' input
reg[31:0] b_latched; // Latched 'b' input
reg[63:0] product_tmp; // Temporary result
reg negative_output; // If output is negative
reg[5:0] count; // Downward counter (32->0)
reg abp_last; // Level of last ABP request
 
// Sequential logic
always @(posedge sys_clock_i) begin
 
// Initialization
if(sys_reset_i) begin
 
product_o = 0;
abp_ack_o = 0;
negative_output = 0;
count = 6'd0;
abp_last = 0;
 
// New request
end else if(abp_req_i!=abp_last) begin
 
abp_last = abp_req_i; // Latch level of ABP request
count = 6'd32; // Start counter
product_tmp = 0; // Initialize result
a_latched = (!signed_i || !a_i[31]) ? { 32'd0, a_i } : { 32'd0, (~a_i+1'b1) };
b_latched = (!signed_i || !b_i[31]) ? b_i : (~b_i + 1'b1);
negative_output = signed_i && (a_i[31] ^ b_i[31]);
product_o = (!negative_output) ? product_tmp : (~product_tmp+1); // Degugging only
// Calculating
end else if(count>0) begin
 
count = count-1;
if(b_latched[0]==1) product_tmp = product_tmp + a_latched;
a_latched = a_latched << 1;
b_latched = b_latched >> 1;
product_o = (!negative_output) ? product_tmp : (~product_tmp + 1); // Debugging only
 
// Return the result
end else if(count==0) begin
 
abp_ack_o = abp_req_i; // Return the result
product_o = (!negative_output) ? product_tmp : (~product_tmp + 1);
 
end
 
end
 
endmodule
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.