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 |
|