URL
https://opencores.org/ocsvn/altor32/altor32/trunk
Subversion Repositories altor32
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 13 to Rev 14
- ↔ Reverse comparison
Rev 13 → Rev 14
altor32/trunk/rtl/core_fast
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: altor32/trunk/rtl/sim_verilator/makefile
===================================================================
--- altor32/trunk/rtl/sim_verilator/makefile (revision 13)
+++ altor32/trunk/rtl/sim_verilator/makefile (revision 14)
@@ -4,7 +4,7 @@
SIMARGS ?=
# Default core to simulate
-RTL_CORE ?= core_simple
+RTL_CORE ?= core_pipelined
# Waveform trace disabled by default
TRACE?= 0
/altor32/trunk/rtl/core_pipelined/altor32_regfile_sim.v
0,0 → 1,373
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module altor32_regfile_sim |
( |
clk_i, |
rst_i, |
en_i, |
wr_i, |
rs_i, |
rt_i, |
rd_i, |
reg_rs_o, |
reg_rt_o, |
reg_rd_i |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_i /*verilator public*/; |
input wr_i /*verilator public*/; |
input [4:0] rs_i /*verilator public*/; |
input [4:0] rt_i /*verilator public*/; |
input [4:0] rd_i /*verilator public*/; |
output [31:0] reg_rs_o /*verilator public*/; |
output [31:0] reg_rt_o /*verilator public*/; |
input [31:0] reg_rd_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Register file |
reg [31:0] reg_r1_sp; |
reg [31:0] reg_r2_fp; |
reg [31:0] reg_r3; |
reg [31:0] reg_r4; |
reg [31:0] reg_r5; |
reg [31:0] reg_r6; |
reg [31:0] reg_r7; |
reg [31:0] reg_r8; |
reg [31:0] reg_r9_lr; |
reg [31:0] reg_r10; |
reg [31:0] reg_r11; |
reg [31:0] reg_r12; |
reg [31:0] reg_r13; |
reg [31:0] reg_r14; |
reg [31:0] reg_r15; |
reg [31:0] reg_r16; |
reg [31:0] reg_r17; |
reg [31:0] reg_r18; |
reg [31:0] reg_r19; |
reg [31:0] reg_r20; |
reg [31:0] reg_r21; |
reg [31:0] reg_r22; |
reg [31:0] reg_r23; |
reg [31:0] reg_r24; |
reg [31:0] reg_r25; |
reg [31:0] reg_r26; |
reg [31:0] reg_r27; |
reg [31:0] reg_r28; |
reg [31:0] reg_r29; |
reg [31:0] reg_r30; |
reg [31:0] reg_r31; |
|
reg [31:0] reg_rs_o; |
reg [31:0] reg_rt_o; |
|
//----------------------------------------------------------------- |
// Register File (for simulation) |
//----------------------------------------------------------------- |
|
// Synchronous register write back |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
reg_r1_sp <= 32'h00000000; |
reg_r2_fp <= 32'h00000000; |
reg_r3 <= 32'h00000000; |
reg_r4 <= 32'h00000000; |
reg_r5 <= 32'h00000000; |
reg_r6 <= 32'h00000000; |
reg_r7 <= 32'h00000000; |
reg_r8 <= 32'h00000000; |
reg_r9_lr <= 32'h00000000; |
reg_r10 <= 32'h00000000; |
reg_r11 <= 32'h00000000; |
reg_r12 <= 32'h00000000; |
reg_r13 <= 32'h00000000; |
reg_r14 <= 32'h00000000; |
reg_r15 <= 32'h00000000; |
reg_r16 <= 32'h00000000; |
reg_r17 <= 32'h00000000; |
reg_r18 <= 32'h00000000; |
reg_r19 <= 32'h00000000; |
reg_r20 <= 32'h00000000; |
reg_r21 <= 32'h00000000; |
reg_r22 <= 32'h00000000; |
reg_r23 <= 32'h00000000; |
reg_r24 <= 32'h00000000; |
reg_r25 <= 32'h00000000; |
reg_r26 <= 32'h00000000; |
reg_r27 <= 32'h00000000; |
reg_r28 <= 32'h00000000; |
reg_r29 <= 32'h00000000; |
reg_r30 <= 32'h00000000; |
reg_r31 <= 32'h00000000; |
end |
else if (en_i == 1'b1) |
begin |
if (wr_i == 1'b1) |
case (rd_i[4:0]) |
5'b00001 : |
reg_r1_sp <= reg_rd_i; |
5'b00010 : |
reg_r2_fp <= reg_rd_i; |
5'b00011 : |
reg_r3 <= reg_rd_i; |
5'b00100 : |
reg_r4 <= reg_rd_i; |
5'b00101 : |
reg_r5 <= reg_rd_i; |
5'b00110 : |
reg_r6 <= reg_rd_i; |
5'b00111 : |
reg_r7 <= reg_rd_i; |
5'b01000 : |
reg_r8 <= reg_rd_i; |
5'b01001 : |
reg_r9_lr <= reg_rd_i; |
5'b01010 : |
reg_r10 <= reg_rd_i; |
5'b01011 : |
reg_r11 <= reg_rd_i; |
5'b01100 : |
reg_r12 <= reg_rd_i; |
5'b01101 : |
reg_r13 <= reg_rd_i; |
5'b01110 : |
reg_r14 <= reg_rd_i; |
5'b01111 : |
reg_r15 <= reg_rd_i; |
5'b10000 : |
reg_r16 <= reg_rd_i; |
5'b10001 : |
reg_r17 <= reg_rd_i; |
5'b10010 : |
reg_r18 <= reg_rd_i; |
5'b10011 : |
reg_r19 <= reg_rd_i; |
5'b10100 : |
reg_r20 <= reg_rd_i; |
5'b10101 : |
reg_r21 <= reg_rd_i; |
5'b10110 : |
reg_r22 <= reg_rd_i; |
5'b10111 : |
reg_r23 <= reg_rd_i; |
5'b11000 : |
reg_r24 <= reg_rd_i; |
5'b11001 : |
reg_r25 <= reg_rd_i; |
5'b11010 : |
reg_r26 <= reg_rd_i; |
5'b11011 : |
reg_r27 <= reg_rd_i; |
5'b11100 : |
reg_r28 <= reg_rd_i; |
5'b11101 : |
reg_r29 <= reg_rd_i; |
5'b11110 : |
reg_r30 <= reg_rd_i; |
5'b11111 : |
reg_r31 <= reg_rd_i; |
default : |
; |
endcase |
end |
end |
|
// Asynchronous Register read (Rs & Rd) |
always @ (rs_i or rt_i or reg_r1_sp or reg_r2_fp or reg_r3 or reg_r4 or reg_r5 or reg_r6 or reg_r7 or reg_r8 or reg_r9_lr or reg_r10 or reg_r11 or reg_r12 or reg_r13 or reg_r14 or reg_r15 or reg_r16 or reg_r17 or reg_r18 or reg_r19 or reg_r20 or reg_r21 or reg_r22 or reg_r23 or reg_r24 or reg_r25 or reg_r26 or reg_r27 or reg_r28 or reg_r29 or reg_r30 or reg_r31 ) |
begin |
case (rs_i) |
5'b00000 : |
reg_rs_o = 32'h00000000; |
5'b00001 : |
reg_rs_o = reg_r1_sp; |
5'b00010 : |
reg_rs_o = reg_r2_fp; |
5'b00011 : |
reg_rs_o = reg_r3; |
5'b00100 : |
reg_rs_o = reg_r4; |
5'b00101 : |
reg_rs_o = reg_r5; |
5'b00110 : |
reg_rs_o = reg_r6; |
5'b00111 : |
reg_rs_o = reg_r7; |
5'b01000 : |
reg_rs_o = reg_r8; |
5'b01001 : |
reg_rs_o = reg_r9_lr; |
5'b01010 : |
reg_rs_o = reg_r10; |
5'b01011 : |
reg_rs_o = reg_r11; |
5'b01100 : |
reg_rs_o = reg_r12; |
5'b01101 : |
reg_rs_o = reg_r13; |
5'b01110 : |
reg_rs_o = reg_r14; |
5'b01111 : |
reg_rs_o = reg_r15; |
5'b10000 : |
reg_rs_o = reg_r16; |
5'b10001 : |
reg_rs_o = reg_r17; |
5'b10010 : |
reg_rs_o = reg_r18; |
5'b10011 : |
reg_rs_o = reg_r19; |
5'b10100 : |
reg_rs_o = reg_r20; |
5'b10101 : |
reg_rs_o = reg_r21; |
5'b10110 : |
reg_rs_o = reg_r22; |
5'b10111 : |
reg_rs_o = reg_r23; |
5'b11000 : |
reg_rs_o = reg_r24; |
5'b11001 : |
reg_rs_o = reg_r25; |
5'b11010 : |
reg_rs_o = reg_r26; |
5'b11011 : |
reg_rs_o = reg_r27; |
5'b11100 : |
reg_rs_o = reg_r28; |
5'b11101 : |
reg_rs_o = reg_r29; |
5'b11110 : |
reg_rs_o = reg_r30; |
5'b11111 : |
reg_rs_o = reg_r31; |
default : |
reg_rs_o = 32'h00000000; |
endcase |
|
case (rt_i) |
5'b00000 : |
reg_rt_o = 32'h00000000; |
5'b00001 : |
reg_rt_o = reg_r1_sp; |
5'b00010 : |
reg_rt_o = reg_r2_fp; |
5'b00011 : |
reg_rt_o = reg_r3; |
5'b00100 : |
reg_rt_o = reg_r4; |
5'b00101 : |
reg_rt_o = reg_r5; |
5'b00110 : |
reg_rt_o = reg_r6; |
5'b00111 : |
reg_rt_o = reg_r7; |
5'b01000 : |
reg_rt_o = reg_r8; |
5'b01001 : |
reg_rt_o = reg_r9_lr; |
5'b01010 : |
reg_rt_o = reg_r10; |
5'b01011 : |
reg_rt_o = reg_r11; |
5'b01100 : |
reg_rt_o = reg_r12; |
5'b01101 : |
reg_rt_o = reg_r13; |
5'b01110 : |
reg_rt_o = reg_r14; |
5'b01111 : |
reg_rt_o = reg_r15; |
5'b10000 : |
reg_rt_o = reg_r16; |
5'b10001 : |
reg_rt_o = reg_r17; |
5'b10010 : |
reg_rt_o = reg_r18; |
5'b10011 : |
reg_rt_o = reg_r19; |
5'b10100 : |
reg_rt_o = reg_r20; |
5'b10101 : |
reg_rt_o = reg_r21; |
5'b10110 : |
reg_rt_o = reg_r22; |
5'b10111 : |
reg_rt_o = reg_r23; |
5'b11000 : |
reg_rt_o = reg_r24; |
5'b11001 : |
reg_rt_o = reg_r25; |
5'b11010 : |
reg_rt_o = reg_r26; |
5'b11011 : |
reg_rt_o = reg_r27; |
5'b11100 : |
reg_rt_o = reg_r28; |
5'b11101 : |
reg_rt_o = reg_r29; |
5'b11110 : |
reg_rt_o = reg_r30; |
5'b11111 : |
reg_rt_o = reg_r31; |
default : |
reg_rt_o = 32'h00000000; |
endcase |
end |
|
endmodule |
/altor32/trunk/rtl/core_pipelined/altor32_regfile_xil.v
0,0 → 1,143
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module altor32_regfile_xil |
( |
clk_i, |
rst_i, |
en_i, |
wr_i, |
rs_i, |
rt_i, |
rd_i, |
reg_rs_o, |
reg_rt_o, |
reg_rd_i |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_i /*verilator public*/; |
input wr_i /*verilator public*/; |
input [4:0] rs_i /*verilator public*/; |
input [4:0] rt_i /*verilator public*/; |
input [4:0] rd_i /*verilator public*/; |
output [31:0] reg_rs_o /*verilator public*/; |
output [31:0] reg_rt_o /*verilator public*/; |
input [31:0] reg_rd_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [4:0] addr_write; |
wire [31:0] data_out1; |
wire [31:0] data_out2; |
reg write_enable; |
wire [31:0] data_out1a; |
wire [31:0] data_out1b; |
wire [31:0] data_out2a; |
wire [31:0] data_out2b; |
wire wea; |
wire web; |
|
reg [31:0] reg_rs_o; |
reg [31:0] reg_rt_o; |
|
//----------------------------------------------------------------- |
// Async Read Process |
//----------------------------------------------------------------- |
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i) |
begin |
// Read Rs |
if (rs_i == 5'b00000) |
reg_rs_o <= 32'h00000000; |
else |
reg_rs_o <= data_out1; |
|
// Read Rt |
if (rt_i == 5'b00000) |
reg_rt_o <= 32'h00000000; |
else |
reg_rt_o <= data_out2; |
|
// Write enabled? |
addr_write <= rd_i[4:0]; |
if ((rd_i != 5'b00000) & (wr_i == 1'b1)) |
write_enable <= 1'b1; |
else |
write_enable <= 1'b0; |
end |
|
//----------------------------------------------------------------- |
// Register File (using RAM16X1D ) |
//----------------------------------------------------------------- |
generate |
begin |
genvar i; |
for (i=0;i<32;i=i+1) |
begin : reg_loop |
RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1a[i]), .SPO(/* open */)); |
RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1b[i]), .SPO(/* open */)); |
RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2a[i]), .SPO(/* open */)); |
RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2b[i]), .SPO(/* open */)); |
end |
end |
endgenerate |
|
//----------------------------------------------------------------- |
// Combinatorial Assignments |
//----------------------------------------------------------------- |
assign data_out1 = (rs_i[4] == 1'b0) ? data_out1a : data_out1b; |
assign data_out2 = (rt_i[4] == 1'b0) ? data_out2a : data_out2b; |
assign wea = (write_enable & ~ (addr_write[4])); |
assign web = (write_enable & addr_write[4]); |
|
endmodule |
/altor32/trunk/rtl/core_pipelined/altor32_funcs.v
0,0 → 1,363
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// shift_left: Shift left by specified amount |
// Inputs: x = input, y = shift amount |
// Return: x << y |
//----------------------------------------------------------------- |
function [31:0] shift_left; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] shift1l; |
reg [31:0] shift2l; |
reg [31:0] shift4l; |
reg [31:0] shift8l; |
reg [31:0] shift16l; |
begin |
if (y[0] == 1'b1) |
shift1l = {x[30:0],1'b0}; |
else |
shift1l = x; |
|
if (y[1] == 1'b1) |
shift2l = {shift1l[29:0],2'b00}; |
else |
shift2l = shift1l; |
|
if (y[2] == 1'b1) |
shift4l = {shift2l[27:0],4'b0000}; |
else |
shift4l = shift2l; |
|
if (y[3] == 1'b1) |
shift8l = {shift4l[23:0],8'b00000000}; |
else |
shift8l = shift4l; |
|
if (y[4] == 1'b1) |
shift16l = {shift8l[15:0],16'b0000000000000000}; |
else |
shift16l = shift8l; |
|
shift_left = shift16l; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// shift_right: Shift right by specified amount |
// Inputs: x = input, y = shift amount |
// Return: x >> y |
//----------------------------------------------------------------- |
function [31:0] shift_right; |
input [31:0] x; |
input [31:0] y; |
reg [31:16] fill; |
reg [31:0] shift1r; |
reg [31:0] shift2r; |
reg [31:0] shift4r; |
reg [31:0] shift8r; |
reg [31:0] shift16r; |
begin |
fill = 16'b0000000000000000; |
if (y[0] == 1'b1) |
shift1r = {fill[31],x[31:1]}; |
else |
shift1r = x; |
|
if (y[1] == 1'b1) |
shift2r = {fill[31:30],shift1r[31:2]}; |
else |
shift2r = shift1r; |
|
if (y[2] == 1'b1) |
shift4r = {fill[31:28],shift2r[31:4]}; |
else |
shift4r = shift2r; |
|
if (y[3] == 1'b1) |
shift8r = {fill[31:24],shift4r[31:8]}; |
else |
shift8r = shift4r; |
|
if (y[4] == 1'b1) |
shift16r = {fill[31:16],shift8r[31:16]}; |
else |
shift16r = shift8r; |
|
shift_right = shift16r; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// shift_right_arith: Shift right by specified amount (sign extend) |
// Inputs: x = input, y = shift amount |
// Return: (int)x >> y |
//----------------------------------------------------------------- |
function [31:0] shift_right_arith; |
input [31:0] x; |
input [31:0] y; |
reg [31:16] fill; |
reg [31:0] shift1r; |
reg [31:0] shift2r; |
reg [31:0] shift4r; |
reg [31:0] shift8r; |
reg [31:0] shift16r; |
begin |
if (x[31] == 1'b1) |
fill = 16'b1111111111111111; |
else |
fill = 16'b0000000000000000; |
|
if (y[0] == 1'b1) |
shift1r = {fill[31],x[31:1]}; |
else |
shift1r = x; |
|
if (y[1] == 1'b1) |
shift2r = {fill[31:30],shift1r[31:2]}; |
else |
shift2r = shift1r; |
|
if (y[2] == 1'b1) |
shift4r = {fill[31:28],shift2r[31:4]}; |
else |
shift4r = shift2r; |
|
if (y[3] == 1'b1) |
shift8r = {fill[31:24],shift4r[31:8]}; |
else |
shift8r = shift4r; |
|
if (y[4] == 1'b1) |
shift16r = {fill[31:16],shift8r[31:16]}; |
else |
shift16r = shift8r; |
|
shift_right_arith = shift16r; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_signed: Less than operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x < (int)y |
//----------------------------------------------------------------- |
function [0:0] less_than_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (x - y); |
if (x[31] != y[31]) |
less_than_signed = x[31]; |
else |
less_than_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_equal_signed: Less than or equal to operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x <= (int)y |
//----------------------------------------------------------------- |
function [0:0] less_than_equal_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (x - y); |
if (x == y) |
less_than_equal_signed = 1'b1; |
else if (x[31] != y[31]) |
less_than_equal_signed = x[31]; |
else |
less_than_equal_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// greater_than_signed: Greater than operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x > (int)y |
//----------------------------------------------------------------- |
function [0:0] greater_than_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (y - x); |
if (x[31] != y[31]) |
greater_than_signed = y[31]; |
else |
greater_than_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// greater_than_equal_signed: Greater than or equal to operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x >= (int)y |
//----------------------------------------------------------------- |
function [0:0] greater_than_equal_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (y - x); |
if (x == y) |
greater_than_equal_signed = 1'b1; |
else if (x[31] != y[31]) |
greater_than_equal_signed = y[31]; |
else |
greater_than_equal_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// sign_extend_imm16: Extend 16-bit signed value to 32-bit signed. |
// Inputs: x = operand |
// Return: (int)((short)x) |
//----------------------------------------------------------------- |
function [31:0] sign_extend_imm16; |
input [15:0] x; |
reg [31:0] y; |
begin |
if (x[15] == 1'b0) |
y[31:16] = 16'b0000000000000000; |
else |
y[31:16] = 16'b1111111111111111; |
|
y[15:0] = x; |
sign_extend_imm16 = y; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// sign_extend_imm26: Extend 26-bit signed value to 32-bit signed. |
// Inputs: x = operand |
// Return: (int)((short)x) |
//----------------------------------------------------------------- |
function [31:0] sign_extend_imm26; |
input [25:0] x; |
reg [31:0] y; |
begin |
if (x[25] == 1'b0) |
y[31:26] = 6'b000000; |
else |
y[31:26] = 6'b111111; |
|
y[25:0] = x; |
sign_extend_imm26 = y; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// extend_imm16: Extend 16-bit unsigned value to 32-bit unsigned. |
// Inputs: x = operand |
// Return: (unsigned int)x |
//----------------------------------------------------------------- |
function [31:0] extend_imm16; |
input [15:0] x; |
begin |
extend_imm16 = {16'h0000,x}; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_zero: Is signed value less than 0? |
// Inputs: x = operand |
// Return: ((int)x) < 0 |
//----------------------------------------------------------------- |
function [0:0] less_than_zero; |
input [31:0] x; |
begin |
if ((x != 32'h00000000) & (x[31] == 1'b1)) |
less_than_zero = 1'b1; |
else |
less_than_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_equal_zero: Is signed value less than or equal to 0? |
// Inputs: x = operand |
// Return: ((int)x) <= 0 |
//----------------------------------------------------------------- |
function [0:0] less_than_equal_zero; |
input [31:0] x; |
begin |
if ((x == 32'h00000000) | (x[31] == 1'b1)) |
less_than_equal_zero = 1'b1; |
else |
less_than_equal_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// more_than_equal_zero: Is signed value more than or equal to 0? |
// Inputs: x = operand |
// Return: ((int)x) >= 0 |
//----------------------------------------------------------------- |
function [0:0] more_than_equal_zero; |
input [31:0] x; |
begin |
if ((x == 32'h00000000) | (x[31] == 1'b0)) |
more_than_equal_zero = 1'b1; |
else |
more_than_equal_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// more_than_equal_zero: Is signed value more than 0? |
// Inputs: x = operand |
// Return: ((int)x) > 0 |
//----------------------------------------------------------------- |
function [0:0] more_than_zero; |
input [31:0] x; |
begin |
if (((x != 32'h00000000) & (x[31] == 1'b0))) |
more_than_zero = 1'b1; |
else |
more_than_zero = 1'b0; |
end |
endfunction |
/altor32/trunk/rtl/core_pipelined/altor32.v
0,0 → 1,1460
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module altor32 |
( |
// General |
clk_i, |
rst_i, |
en_i, |
intr_i, |
fault_o, |
break_o, |
|
// Memory Interface |
mem_addr_o, |
mem_data_out_o, |
mem_data_in_i, |
mem_wr_o, |
mem_rd_o, |
mem_pause_i, |
|
// Status/Debug |
dbg_pc_o |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] BOOT_VECTOR = 32'h00000100; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
// General |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_i /*verilator public*/; |
input intr_i /*verilator public*/; |
output fault_o /*verilator public*/; |
output break_o /*verilator public*/; |
|
// Memory Interface |
output [31:0] mem_addr_o /*verilator public*/; |
output [31:0] mem_data_out_o /*verilator public*/; |
input [31:0] mem_data_in_i /*verilator public*/; |
output [3:0] mem_wr_o /*verilator public*/; |
output mem_rd_o /*verilator public*/; |
input mem_pause_i /*verilator public*/; |
|
// Status/Debug |
output [31:0] dbg_pc_o /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Current program counter |
reg [31:0] r_pc; |
|
// Current program counter (delayed) |
reg [31:0] d_pc; |
|
// Exception saved program counter |
reg [31:0] r_epc; |
|
// Supervisor register |
reg [31:0] r_sr; |
|
// Exception saved supervisor register |
reg [31:0] r_esr; |
|
// Register number (rA) |
wire [4:0] r_ra; |
|
// Register number (rB) |
wire [4:0] r_rb; |
|
// Destination register number (pre execute stage) |
wire [4:0] r_rd; |
|
// Destination register number (post execute stage) |
reg [4:0] r_rd_wb; |
|
// Destination register number (delayed) |
reg [4:0] d_rd_wb; |
|
// Destination register number (delayed by 2 clocks) |
reg [4:0] d2_rd_wb; |
|
// Register value (rA) |
wire [31:0] r_reg_ra; |
|
// Register value (rB) |
wire [31:0] r_reg_rb; |
|
// Current opcode |
reg [31:0] r_opcode; |
|
// Current opcode (delayed) |
reg [31:0] d_opcode; |
|
// Execute result output (non-ALU) |
reg [31:0] r_reg_result; |
|
// Execute result output (delayed) |
reg [31:0] d_reg_result; |
|
// Register writeback value |
reg [31:0] r_reg_rd; |
|
// Register writeback enable |
reg r_writeback; |
|
// Memory operation address (data only) |
reg [31:0] mem_addr; |
|
// Memory operation write data |
reg [31:0] mem_data_out; |
|
// Memory operation write mask |
reg [3:0] mem_wr; |
|
// Memory read operation |
reg mem_rd; |
|
// Memory operation byte/word select |
reg [1:0] mem_offset; |
|
// Memory operation byte/word select (delayed) |
reg [1:0] d_mem_offset; |
|
// Memory operation occurring |
reg r_mem_access; |
|
// Memory operation (delayed) |
reg d_mem_access; |
|
// ALU input A |
reg [31:0] alu_a; |
|
// ALU input B |
reg [31:0] alu_b; |
|
// ALU output |
wire [31:0] alu_result; |
|
// ALU output (delayed) |
reg [31:0] d_alu_result; |
|
// ALU operation selection |
reg [3:0] alu_func; |
|
// ALU operation selection (delayed) |
reg [3:0] d_alu_func; |
|
// Fault output |
reg fault_o; |
|
// Break/Trap output |
reg break_o; |
|
// Memory output signals |
wire [31:0] mem_addr_o; |
wire [31:0] mem_addr_mux; |
wire [31:0] mem_data_out_o; |
wire [31:0] mem_data_in; |
wire [3:0] mem_wr_o; |
wire mem_rd_o; |
|
// Was the last instruction a load operation? |
reg r_load_inst; |
|
// Last memory address (used during stalls) |
reg [31:0] mem_addr_last; |
|
// Branch delay slot |
reg r_branch_dslot; |
|
// Branch target |
reg [31:0] r_pc_branch; |
|
// Flush next instruction from the pipeline |
reg r_flush_next; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// ALU |
altor32_alu alu |
( |
.input_a(alu_a), |
.input_b(alu_b), |
.func(alu_func), |
.result(alu_result) |
); |
|
// Register file |
`ifdef CONF_TARGET_SIM |
altor32_regfile_sim |
`else |
altor32_regfile_xil |
`endif |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.en_i(1'b1), |
.wr_i(r_writeback), |
|
// Tri-port |
.rs_i(r_ra), |
.rt_i(r_rb), |
.rd_i(d2_rd_wb), |
.reg_rs_o(r_reg_ra), |
.reg_rt_o(r_reg_rb), |
.reg_rd_i(r_reg_rd) |
); |
|
//------------------------------------------------------------------- |
// Pipeline |
//------------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
d_opcode <= 32'h00000000; |
d_rd_wb <= 5'b00000; |
d2_rd_wb <= 5'b00000; |
d_reg_result <= 32'h00000000; |
d_alu_result <= 32'h00000000; |
d_alu_func <= 4'b0000; |
d_mem_offset <= 2'b00; |
d_mem_access <= 1'b0; |
d_pc <= 32'h00000000; |
mem_addr_last <= 32'h00000000; |
end |
else if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) |
begin |
d_opcode <= r_opcode; |
d_rd_wb <= r_rd_wb; |
d2_rd_wb <= d_rd_wb; |
d_reg_result <= r_reg_result; |
d_alu_result <= alu_result; |
d_alu_func <= alu_func; |
d_mem_offset <= mem_offset; |
d_mem_access <= r_mem_access; |
d_pc <= r_pc; |
|
if (r_mem_access == 1'b1) |
mem_addr_last <= mem_addr; |
else |
mem_addr_last <= r_pc; |
end |
end |
|
|
//------------------------------------------------------------------- |
// Execute: Execute opcode |
//------------------------------------------------------------------- |
|
// Execute stage blocking assignment vars |
reg [7:0] v_inst; |
reg [4:0] v_ra; |
reg [4:0] v_rb; |
reg [4:0] v_rd; |
reg [7:0] v_alu_op; |
reg [1:0] v_shift_op; |
reg [15:0] v_sfxx_op; |
reg [15:0] v_imm; |
reg [31:0] v_imm_uint32; |
reg [31:0] v_imm_int32; |
reg [31:0] v_store_imm; |
reg [15:0] v_mxspr_imm; |
reg [31:0] v_target; |
reg [31:0] v_reg_ra; |
reg [31:0] v_reg_rb; |
reg [31:0] v_pc; |
reg [31:0] v_reg_result; |
reg [31:0] v_offset; |
reg [31:0] v_shift_val; |
reg [31:0] v_shift_imm; |
reg [31:0] v_vector; |
reg [31:0] v_sr; |
reg [31:0] v_mem_addr; |
reg [31:0] v_mem_data_in; |
reg v_exception; |
reg v_branch; |
reg v_jmp; |
reg v_write_rd; |
reg v_mem_access; |
reg v_load_stall; |
reg v_no_intr; |
|
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
r_pc <= BOOT_VECTOR; |
|
r_epc <= 32'h00000000; |
r_sr <= 32'h00000000; |
r_esr <= 32'h00000000; |
r_rd_wb <= 5'b00000; |
r_load_inst <= 1'b0; |
|
r_branch_dslot <= 1'b0; |
r_pc_branch <= 32'h00000000; |
|
// Flush first instruction execute to allow fetch to occur |
r_flush_next <= 1'b1; |
|
r_opcode <= 32'h00000000; |
|
// Default to no ALU operation |
alu_func <= `ALU_NONE; |
|
mem_addr <= 32'h00000000; |
mem_data_out <= 32'h00000000; |
mem_rd <= 1'b0; |
mem_wr <= 4'b0000; |
mem_offset <= 2'b00; |
|
fault_o <= 1'b0; |
break_o <= 1'b0; |
r_mem_access <= 1'b0; |
end |
// Enabled & memory not busy |
else if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) |
begin |
|
mem_rd <= 1'b0; |
mem_wr <= 4'b0000; |
break_o <= 1'b0; |
|
v_exception = 1'b0; |
v_vector = 32'h00000000; |
v_branch = 1'b0; |
v_jmp = 1'b0; |
v_write_rd = 1'b0; |
v_sr = r_sr; |
v_mem_access = 1'b0; |
v_load_stall = 1'b0; |
v_no_intr = 1'b0; |
v_mem_data_in = mem_data_in_i; |
|
`ifdef CONF_CORE_DEBUG |
if (d_mem_access == 1'b0) |
$display("%08x: %08x", r_pc, v_mem_data_in); |
else |
$display("%08x: Data In %08x", r_pc, v_mem_data_in); |
`endif |
|
// If memory access was done, check for no instruction to process. |
// As memory access has a 1 cycle latency, invalid mem_data_in_i is |
// aligned with d_mem_access not r_mem_access. |
if (d_mem_access) |
begin |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
`ifdef CONF_CORE_DEBUG |
$display(" - BUBBLE due to no instruction because of data access"); |
`endif |
end |
|
// Flush next instruction for some reason |
if (r_flush_next) |
begin |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
`ifdef CONF_CORE_DEBUG |
$display(" - BUBBLE due to pipeline flush request"); |
`endif |
end |
|
r_flush_next <= 1'b0; |
|
// Decode opcode |
v_rd = v_mem_data_in[25:21]; |
v_ra = v_mem_data_in[20:16]; |
v_rb = v_mem_data_in[15:11]; |
v_alu_op = {v_mem_data_in[9:6],v_mem_data_in[3:0]}; |
v_sfxx_op = {5'b00,v_mem_data_in[31:21]}; |
v_shift_op = v_mem_data_in[7:6]; |
v_target = sign_extend_imm26(v_mem_data_in[25:0]); |
v_store_imm = sign_extend_imm16({v_mem_data_in[25:21],v_mem_data_in[10:0]}); |
|
// Signed & unsigned imm -> 32-bits |
v_imm = v_mem_data_in[15:0]; |
v_imm_int32 = sign_extend_imm16(v_imm); |
v_imm_uint32 = extend_imm16(v_imm); |
|
// Load register[ra] |
v_reg_ra = r_reg_ra; |
|
// Load register[rb] |
v_reg_rb = r_reg_rb; |
|
//--------------------------------------------------------------- |
// Hazard detection |
//--------------------------------------------------------------- |
|
// Register[ra] hazard detection & forwarding logic |
// (higher priority = latest results!) |
if (v_ra != 5'b00000) |
begin |
// Operand from load result (not yet ready) |
if (r_load_inst && v_ra == r_rd_wb) |
begin |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
v_load_stall = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - BUBBLE due to load result not ready R[%d]", v_ra); |
`endif |
end |
else if (v_ra == r_rd_wb) |
begin |
// Result from memory / other |
if (alu_func == `ALU_NONE) |
begin |
v_reg_ra = r_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_ra = alu_result; |
end |
|
`ifdef CONF_CORE_DEBUG |
$display(" - rA[%d] forwarded 0x%08x", v_ra, v_reg_ra); |
`endif |
end |
else if (v_ra == d_rd_wb) |
begin |
|
// Result from memory / other |
if (d_alu_func == `ALU_NONE) |
begin |
v_reg_ra = d_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_ra = d_alu_result; |
end |
|
`ifdef CONF_CORE_DEBUG |
$display(" - rA[%d] forwarded 0x%08x", v_ra, v_reg_ra); |
`endif |
end |
else if (v_ra == d2_rd_wb) |
begin |
v_reg_ra = r_reg_rd; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - rA[%d] forwarded 0x%08x", v_ra, v_reg_ra); |
`endif |
end |
end |
|
// Register[rb] hazard detection & forwarding logic |
// (higher priority = latest results!) |
if (v_rb != 5'b00000) |
begin |
// Operand from load result (not yet ready) |
if (r_load_inst && v_rb == r_rd_wb) |
begin |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
v_load_stall = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - BUBBLE due to load result not ready R[%d]", v_rb); |
`endif |
end |
else if (v_rb == r_rd_wb) |
begin |
// Result from memory / other |
if (alu_func == `ALU_NONE) |
begin |
v_reg_rb = r_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_rb = alu_result; |
end |
|
`ifdef CONF_CORE_DEBUG |
$display(" - rB[%d] forwarded 0x%08x", v_rb, v_reg_rb); |
`endif |
end |
else if (v_rb == d_rd_wb) |
begin |
|
// Result from non ALU function |
if (d_alu_func == `ALU_NONE) |
begin |
v_reg_rb = d_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_rb = d_alu_result; |
end |
|
`ifdef CONF_CORE_DEBUG |
$display(" - rB[%d] forwarded 0x%08x", v_rb, v_reg_rb); |
`endif |
end |
else if (v_rb == d2_rd_wb) |
begin |
v_reg_rb = r_reg_rd; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - rB[%d] forwarded 0x%08x", v_rb, v_reg_rb); |
`endif |
end |
end |
|
// Store opcode (after possible bubble generation) |
r_opcode <= v_mem_data_in; |
|
// Decode instruction |
v_inst = {2'b00,v_mem_data_in[31:26]}; |
|
// Shift ammount (from register[rb]) |
v_shift_val = {26'b00,v_reg_rb[5:0]}; |
|
// Shift ammount (from immediate) |
v_shift_imm = {26'b00,v_imm[5:0]}; |
|
// MTSPR/MFSPR operand |
v_mxspr_imm = (v_reg_ra[15:0] | {5'b000000,v_mem_data_in[10:0]}); |
|
// Zero result |
v_reg_result = 32'h00000000; |
|
// Update PC to next value |
v_pc = (r_pc + 4); |
|
// Default to no ALU operation |
alu_func <= `ALU_NONE; |
|
// Default target is r_rd |
r_rd_wb <= r_rd; |
|
// Reset load instruction state |
r_load_inst <= 1'b0; |
|
// Reset branch delay slot status |
r_branch_dslot <= 1'b0; |
|
//--------------------------------------------------------------- |
// Execute instruction |
//--------------------------------------------------------------- |
case (v_inst) |
`INST_OR32_BUBBLE : |
begin |
// Do not allow external interrupts whilst executing a bubble |
// as this will result in pipeline issues. |
v_no_intr = 1'b1; |
end |
`INST_OR32_ALU : |
begin |
case (v_alu_op) |
`INST_OR32_ADD: // l.add |
begin |
alu_func <= `ALU_ADD; |
alu_a <= v_reg_ra; |
alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_AND: // l.and |
begin |
alu_func <= `ALU_AND; |
alu_a <= v_reg_ra; |
alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_OR: // l.or |
begin |
alu_func <= `ALU_OR; |
alu_a <= v_reg_ra; |
alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SLL: // l.sll |
begin |
alu_func <= `ALU_SHIFTL; |
alu_a <= v_reg_ra; |
alu_b <= v_shift_val; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRA: // l.sra |
begin |
alu_func <= `ALU_SHIRTR_ARITH; |
alu_a <= v_reg_ra; |
alu_b <= v_shift_val; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRL: // l.srl |
begin |
alu_func <= `ALU_SHIFTR; |
alu_a <= v_reg_ra; |
alu_b <= v_shift_val; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SUB: // l.sub |
begin |
alu_func <= `ALU_SUB; |
alu_a <= v_reg_ra; |
alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_XOR: // l.xor |
begin |
alu_func <= `ALU_XOR; |
alu_a <= v_reg_ra; |
alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_ADDI: // l.addi |
begin |
alu_func <= `ALU_ADD; |
alu_a <= v_reg_ra; |
alu_b <= v_imm_int32; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_ANDI: // l.andi |
begin |
alu_func <= `ALU_AND; |
alu_a <= v_reg_ra; |
alu_b <= v_imm_uint32; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_BF: // l.bf |
begin |
if (v_sr[`OR32_SR_F] == 1'b1) |
v_branch = 1'b1; |
end |
|
`INST_OR32_BNF: // l.bnf |
begin |
if (v_sr[`OR32_SR_F] == 1'b0) |
v_branch = 1'b1; |
end |
|
`INST_OR32_J: // l.j |
begin |
v_branch = 1'b1; |
end |
|
`INST_OR32_JAL: // l.jal |
begin |
v_reg_result = v_pc; |
v_write_rd = 1'b1; |
r_rd_wb <= 5'b01001; // Write to REG_9_LR |
|
v_branch = 1'b1; |
end |
|
`INST_OR32_JALR: // l.jalr |
begin |
v_reg_result = v_pc; |
v_write_rd = 1'b1; |
r_rd_wb <= 5'b01001; // Write to REG_9_LR |
|
v_pc = v_reg_rb; |
v_jmp = 1; |
end |
|
`INST_OR32_JR: // l.jr |
begin |
v_pc = v_reg_rb; |
v_jmp = 1; |
end |
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz |
`INST_OR32_LBS, `INST_OR32_LHS, `INST_OR32_LWS, `INST_OR32_LBZ, `INST_OR32_LHZ, `INST_OR32_LWZ : |
begin |
v_mem_addr = (v_reg_ra + v_imm_int32); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
mem_data_out <= 32'h00000000; |
mem_rd <= 1'b1; |
mem_offset <= v_mem_addr[1:0]; |
v_write_rd = 1'b1; |
v_mem_access = 1'b1; |
r_load_inst <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - Load from 0x%08x", {v_mem_addr[31:2],2'b00}); |
`endif |
end |
|
`INST_OR32_MFSPR: // l.mfspr |
begin |
case (v_mxspr_imm) |
// SR - Supervision register |
`SPR_REG_SR: |
begin |
v_reg_result = v_sr; |
v_write_rd = 1'b1; |
end |
|
// EPCR - EPC Exception saved PC |
`SPR_REG_EPCR: |
begin |
v_reg_result = r_epc; |
v_write_rd = 1'b1; |
end |
|
// ESR - Exception saved SR |
`SPR_REG_ESR: |
begin |
v_reg_result = r_esr; |
v_write_rd = 1'b1; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_MTSPR: // l.mtspr |
begin |
case (v_mxspr_imm) |
// SR - Supervision register |
`SPR_REG_SR: |
begin |
v_sr = v_reg_rb; |
end |
|
// EPCR - EPC Exception saved PC |
`SPR_REG_EPCR: |
begin |
r_epc <= v_reg_rb; |
end |
|
// ESR - Exception saved SR |
`SPR_REG_ESR: |
begin |
r_esr <= v_reg_rb; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_MOVHI: // l.movhi |
begin |
v_reg_result = {v_imm,16'h0000}; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_NOP: // l.nop |
begin |
|
end |
|
`INST_OR32_ORI: // l.ori |
begin |
alu_func <= `ALU_OR; |
alu_a <= v_reg_ra; |
alu_b <= v_imm_uint32; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_RFE: // l.rfe |
begin |
// TODO: This instruction should not have a delay slot |
// but does in this implementation... |
v_pc = r_epc; |
v_sr = r_esr; |
v_jmp = 1; |
end |
|
`INST_OR32_SHIFTI : |
begin |
case (v_shift_op) |
`INST_OR32_SLLI: // l.slli |
begin |
alu_func <= `ALU_SHIFTL; |
alu_a <= v_reg_ra; |
alu_b <= v_shift_imm; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRAI: // l.srai |
begin |
alu_func <= `ALU_SHIRTR_ARITH; |
alu_a <= v_reg_ra; |
alu_b <= v_shift_imm; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRLI: // l.srli |
begin |
alu_func <= `ALU_SHIFTR; |
alu_a <= v_reg_ra; |
alu_b <= v_shift_imm; |
v_write_rd = 1'b1; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_SB: |
begin |
v_mem_addr = (v_reg_ra + v_store_imm); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
case (v_mem_addr[1:0]) |
2'b00 : |
begin |
mem_data_out <= {v_reg_rb[7:0],24'h000000}; |
mem_wr <= 4'b1000; |
v_mem_access = 1'b1; |
end |
2'b01 : |
begin |
mem_data_out <= {{8'h00,v_reg_rb[7:0]},16'h0000}; |
mem_wr <= 4'b0100; |
v_mem_access = 1'b1; |
end |
2'b10 : |
begin |
mem_data_out <= {{16'h0000,v_reg_rb[7:0]},8'h00}; |
mem_wr <= 4'b0010; |
v_mem_access = 1'b1; |
end |
2'b11 : |
begin |
mem_data_out <= {24'h000000,v_reg_rb[7:0]}; |
mem_wr <= 4'b0001; |
v_mem_access = 1'b1; |
end |
default : |
begin |
mem_data_out <= 32'h00000000; |
mem_wr <= 4'b0000; |
end |
endcase |
end |
|
`INST_OR32_SFXX, `INST_OR32_SFXXI: |
begin |
case (v_sfxx_op) |
`INST_OR32_SFEQ: // l.sfeq |
begin |
if (v_reg_ra == v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFEQI: // l.sfeqi |
begin |
if (v_reg_ra == v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGES: // l.sfges |
begin |
if (greater_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGESI: // l.sfgesi |
begin |
if (greater_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGEU: // l.sfgeu |
begin |
if (v_reg_ra >= v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGEUI: // l.sfgeui |
begin |
if (v_reg_ra >= v_imm_uint32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTS: // l.sfgts |
begin |
if (greater_than_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTSI: // l.sfgtsi |
begin |
if (greater_than_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTU: // l.sfgtu |
begin |
if (v_reg_ra > v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTUI: // l.sfgtui |
begin |
if (v_reg_ra > v_imm_uint32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLES: // l.sfles |
begin |
if (less_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLESI: // l.sflesi |
begin |
if (less_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLEU: // l.sfleu |
begin |
if (v_reg_ra <= v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLEUI: // l.sfleui |
begin |
if (v_reg_ra <= v_imm_uint32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTS: // l.sflts |
begin |
if (less_than_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTSI: // l.sfltsi |
begin |
if (less_than_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTU: // l.sfltu |
begin |
if (v_reg_ra < v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTUI: // l.sfltui |
begin |
if (v_reg_ra < v_imm_uint32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFNE: // l.sfne |
begin |
if (v_reg_ra != v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFNEI: // l.sfnei |
begin |
if (v_reg_ra != v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_SH: // l.sh |
begin |
v_mem_addr = (v_reg_ra + v_store_imm); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
case (v_mem_addr[1:0]) |
2'b00 : |
begin |
mem_data_out <= {v_reg_rb[15:0],16'h0000}; |
mem_wr <= 4'b1100; |
v_mem_access = 1'b1; |
end |
2'b10 : |
begin |
mem_data_out <= {16'h0000,v_reg_rb[15:0]}; |
mem_wr <= 4'b0011; |
v_mem_access = 1'b1; |
end |
default : |
begin |
mem_data_out <= 32'h00000000; |
mem_wr <= 4'b0000; |
end |
endcase |
end |
|
`INST_OR32_SW: // l.sw |
begin |
v_mem_addr = (v_reg_ra + v_store_imm); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
mem_data_out <= v_reg_rb; |
mem_wr <= 4'b1111; |
v_mem_access = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - Store to 0x%08x = 0x%08x", {v_mem_addr[31:2],2'b00}, v_reg_rb); |
`endif |
end |
|
`INST_OR32_MISC: |
begin |
case (v_mem_data_in[31:24]) |
`INST_OR32_SYS: // l.sys |
begin |
v_exception = 1'b1; |
v_vector = `VECTOR_SYSCALL; |
end |
|
`INST_OR32_TRAP: // l.trap |
begin |
v_exception = 1'b1; |
v_vector = `VECTOR_TRAP; |
break_o <= 1'b1; |
end |
|
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_XORI: // l.xori |
begin |
alu_func <= `ALU_XOR; |
alu_a <= v_reg_ra; |
alu_b <= v_imm_int32; |
v_write_rd = 1'b1; |
end |
|
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = `VECTOR_ILLEGAL_INST; |
end |
endcase |
|
//--------------------------------------------------------------- |
// Branch logic |
//--------------------------------------------------------------- |
|
// Handle branches |
if (v_branch == 1'b1) |
begin |
v_offset = {v_target[29:0],2'b00}; |
v_pc = (r_pc + v_offset - 4); |
|
// Next instruction is branch delay slot |
r_branch_dslot <= 1'b1; |
r_pc_branch <= v_pc; |
|
// Don't service external interrupts before executing branch delay slot. |
v_no_intr = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - Branch to 0x%08x", v_pc); |
`endif |
end |
// Handle jumps |
else if (v_jmp == 1'b1) |
begin |
// Next instruction is branch delay slot |
r_branch_dslot <= 1'b1; |
r_pc_branch <= v_pc; |
|
// Don't service external interrupts before executing branch delay slot. |
v_no_intr = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - Jump to 0x%08x", v_pc); |
`endif |
end |
// Exception (Fault/Syscall/Break) |
else if (v_exception == 1'b1) |
begin |
// The value of r_pc cannot be a branch delay slot as the exception |
// causing instruction / fault is not a branch. |
v_sr[`OR32_SR_DSX] = 1'b0; |
|
// Save PC (exception causing PC+4) & SR |
r_epc <= r_pc; |
r_esr <= v_sr; |
|
// Disable further interrupts |
v_sr = 0; |
|
// Set PC to exception vector |
v_pc = v_vector; |
r_pc <= v_pc; |
|
// Do not execute next instruction which will be exception |
// PC + 4. This allows the PC change latency to take effect. |
r_flush_next <= 1'b1; |
|
// Don't allow external interrupts to occur before servicing the exception |
v_no_intr = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - Exception 0x%08x", v_vector); |
`endif |
end |
|
//--------------------------------------------------------------- |
// PC update logic |
//--------------------------------------------------------------- |
|
// Revert to previous instruction if execution failed? |
if (v_load_stall) |
begin |
// Revert program counter to load instruction + 4 |
// as the instruction failed to execute due to a |
// data dependancy. |
v_pc = d_pc; |
r_pc <= v_pc; |
`ifdef CONF_CORE_DEBUG |
$display(" - Revert PC to failed instruction 0x%08x", v_pc); |
`endif |
end |
// Stall in branch delay slot due to mem access? |
else if (d_mem_access && r_branch_dslot) |
begin |
v_pc = r_pc_branch; |
r_pc <= v_pc; |
|
// Don't allow external interrupts to occur before fetching the next inst. |
v_no_intr = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - Override PC to 0x%08x (BDS in mem shaddow)", r_pc_branch); |
`endif |
end |
// Update to new PC value only if last cycle wasn't a memory access |
// (as instruction fetch would not occur as memory bus in-use by data access) |
else if (r_mem_access == 1'b0) |
begin |
r_pc <= v_pc; |
`ifdef CONF_CORE_DEBUG |
$display(" - Update PC to 0x%08x", v_pc); |
`endif |
end |
|
//--------------------------------------------------------------- |
// External interrupt logic |
//--------------------------------------------------------------- |
// If external interrupts are not blocked on this cycle and there |
// is an interrupt pending (plus interrupts are enabled) |
if (v_no_intr == 1'b0 && intr_i && v_sr[`OR32_SR_IEE]) |
begin |
// Save PC (PC+4) & SR |
r_epc <= r_pc; |
r_esr <= v_sr; |
|
// Disable further interrupts |
v_sr = 0; |
|
// Set PC to external interrupt vector |
v_pc = `VECTOR_EXTINT; |
r_pc <= v_pc; |
|
// Do not execute next instruction which will be PC + 4. |
// This allows the PC change latency to take effect. |
r_flush_next <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" - External Interrupt 0x%08x", v_vector); |
`endif |
end |
|
// Update other registers with variable values |
r_sr <= v_sr; |
r_reg_result <= v_reg_result; |
r_mem_access <= v_mem_access; |
|
// No writeback required? |
if (v_write_rd == 1'b0) |
begin |
// Target register is R0 which is read-only |
r_rd_wb <= 5'b00000; |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Writeback |
//------------------------------------------------------------------- |
reg [31:0] wb_v_reg_result; |
reg [7:0] wb_v_inst; |
|
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
r_writeback <= 1'b1; |
end |
else |
begin |
r_writeback <= 1'b0; |
|
if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) |
begin |
|
wb_v_reg_result = d_reg_result; |
|
// Handle delayed result instructions |
wb_v_inst = {2'b00,d_opcode[31:26]}; |
case (wb_v_inst) |
`INST_OR32_LBS: // l.lbs |
begin |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; |
2'b01 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; |
2'b10 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; |
2'b11 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
// Sign extend LB |
if (wb_v_reg_result[7] == 1'b1) |
wb_v_reg_result = {24'hFFFFFF,wb_v_reg_result[7:0]}; |
end |
|
`INST_OR32_LBZ: // l.lbz |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; |
2'b01 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; |
2'b10 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; |
2'b11 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
`INST_OR32_LHS: // l.lhs |
begin |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; |
2'b10 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
// Sign extend LH |
if (wb_v_reg_result[15] == 1'b1) |
wb_v_reg_result = {16'hFFFF,wb_v_reg_result[15:0]}; |
end |
|
`INST_OR32_LHZ: // l.lhz |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; |
2'b10 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
`INST_OR32_LWZ, `INST_OR32_LWS: // l.lwz l.lws |
wb_v_reg_result = mem_data_in_i; |
|
default : |
wb_v_reg_result = d_reg_result; |
endcase |
|
// Result from memory / other |
if (d_alu_func == `ALU_NONE) |
begin |
r_reg_rd <= wb_v_reg_result; |
end |
// Result from ALU |
else |
begin |
r_reg_rd <= d_alu_result; |
end |
|
// Register writeback required? |
if (d_rd_wb != 5'b00000) |
begin |
r_writeback <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
if (d_alu_func == `ALU_NONE) |
$display(" - Writeback R%d = 0x%08x", d_rd_wb, wb_v_reg_result); |
else |
$display(" - Writeback R%d = 0x%08x", d_rd_wb, d_alu_result); |
`endif |
end |
end |
end |
end |
|
|
//------------------------------------------------------------------- |
// Combinatorial |
//------------------------------------------------------------------- |
|
// Memory access mux |
assign mem_data_in = mem_data_in_i; |
assign mem_addr_mux = (r_mem_access == 1'b1) ? mem_addr : r_pc; |
assign mem_addr_o = (mem_pause_i == 1'b1) ? mem_addr_last : mem_addr_mux; |
assign mem_data_out_o = mem_data_out; |
assign mem_rd_o = (r_mem_access == 1'b1) ? mem_rd : 1'b1; |
assign mem_wr_o = (mem_pause_i == 1'b0) ? mem_wr : 4'b0000; |
|
// Opcode register decoding |
assign r_rd = mem_data_in_i[25:21]; |
assign r_ra = mem_data_in_i[20:16]; |
assign r_rb = mem_data_in_i[15:11]; |
|
assign dbg_pc_o = r_pc; |
|
`include "altor32_funcs.v" |
|
endmodule |
/altor32/trunk/rtl/core_pipelined/altor32_alu.v
0,0 → 1,92
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module altor32_alu |
( |
input_a, |
input_b, |
func, |
result |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input [31:0] input_a /*verilator public*/; |
input [31:0] input_b /*verilator public*/; |
input [3:0] func /*verilator public*/; |
output [31:0] result /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [31:0] result; |
|
//----------------------------------------------------------------- |
// ALU |
//----------------------------------------------------------------- |
always @ (func or input_a or input_b ) |
begin |
case (func) |
`ALU_SHIFTL : result = shift_left(input_a, input_b); |
`ALU_SHIFTR : result = shift_right(input_a, input_b); |
`ALU_SHIRTR_ARITH: result = shift_right_arith(input_a, input_b); |
`ALU_ADD : result = (input_a + input_b); |
`ALU_SUB : result = (input_a - input_b); |
`ALU_AND : result = (input_a & input_b); |
`ALU_OR : result = (input_a | input_b); |
`ALU_XOR : result = (input_a ^ input_b); |
default : |
result = 32'h00000000; |
endcase |
end |
|
`include "altor32_funcs.v" |
|
endmodule |
/altor32/trunk/rtl/core_pipelined/altor32_defs.v
0,0 → 1,138
//----------------------------------------------------------------- |
// ALU Operations |
//----------------------------------------------------------------- |
`define ALU_NONE 4'b0000 |
`define ALU_SHIFTL 4'b0001 |
`define ALU_SHIFTR 4'b0010 |
`define ALU_SHIRTR_ARITH 4'b0011 |
`define ALU_ADD 4'b0100 |
`define ALU_SUB 4'b0101 |
`define ALU_AND 4'b0110 |
`define ALU_OR 4'b0111 |
`define ALU_XOR 4'b1000 |
|
//----------------------------------------------------------------- |
// ALU Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_ALU 8'h38 |
`define INST_OR32_ADD 8'h00 |
`define INST_OR32_AND 8'h03 |
`define INST_OR32_OR 8'h04 |
`define INST_OR32_SLL 8'h08 |
`define INST_OR32_SRA 8'h28 |
`define INST_OR32_SRL 8'h18 |
`define INST_OR32_SUB 8'h02 |
`define INST_OR32_XOR 8'h05 |
|
//----------------------------------------------------------------- |
// INST_OR32_SHIFTI Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_SHIFTI 8'h2E |
`define INST_OR32_SLLI 2'b00 |
`define INST_OR32_SRAI 2'b10 |
`define INST_OR32_SRLI 2'b01 |
|
//----------------------------------------------------------------- |
// General Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_ADDI 8'h27 |
`define INST_OR32_ANDI 8'h29 |
`define INST_OR32_BF 8'h04 |
`define INST_OR32_BNF 8'h03 |
`define INST_OR32_J 8'h00 |
`define INST_OR32_JAL 8'h01 |
`define INST_OR32_JALR 8'h12 |
`define INST_OR32_JR 8'h11 |
`define INST_OR32_MFSPR 8'h2D |
`define INST_OR32_MOVHI 8'h06 |
`define INST_OR32_MTSPR 8'h30 |
`define INST_OR32_NOP 8'h05 |
`define INST_OR32_ORI 8'h2A |
`define INST_OR32_RFE 8'h09 |
`define INST_OR32_SB 8'h36 |
`define INST_OR32_SH 8'h37 |
`define INST_OR32_SW 8'h35 |
`define INST_OR32_XORI 8'h2B |
`define INST_OR32_LBS 8'h24 |
`define INST_OR32_LBZ 8'h23 |
`define INST_OR32_LHS 8'h26 |
`define INST_OR32_LHZ 8'h25 |
`define INST_OR32_LWZ 8'h21 |
`define INST_OR32_LWS 8'h22 |
|
//----------------------------------------------------------------- |
// Set Flag Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_SFXX 8'h2F |
`define INST_OR32_SFXXI 8'h39 |
`define INST_OR32_SFEQ 16'h0720 |
`define INST_OR32_SFEQI 16'h05E0 |
`define INST_OR32_SFGES 16'h072B |
`define INST_OR32_SFGESI 16'h05EB |
`define INST_OR32_SFGEU 16'h0723 |
`define INST_OR32_SFGEUI 16'h05E3 |
`define INST_OR32_SFGTS 16'h072A |
`define INST_OR32_SFGTSI 16'h05EA |
`define INST_OR32_SFGTU 16'h0722 |
`define INST_OR32_SFGTUI 16'h05E2 |
`define INST_OR32_SFLES 16'h072D |
`define INST_OR32_SFLESI 16'h05ED |
`define INST_OR32_SFLEU 16'h0725 |
`define INST_OR32_SFLEUI 16'h05E5 |
`define INST_OR32_SFLTS 16'h072C |
`define INST_OR32_SFLTSI 16'h05EC |
`define INST_OR32_SFLTU 16'h0724 |
`define INST_OR32_SFLTUI 16'h05E4 |
`define INST_OR32_SFNE 16'h0721 |
`define INST_OR32_SFNEI 16'h05E1 |
|
//----------------------------------------------------------------- |
// Misc Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_MISC 8'h08 |
`define INST_OR32_SYS 8'h20 |
`define INST_OR32_TRAP 8'h21 |
|
`define INST_OR32_BUBBLE 8'h3F |
`define OPCODE_INST_BUBBLE 32'hFC000000 |
|
//----------------------------------------------------------------- |
// SPR Register Map |
//----------------------------------------------------------------- |
`define SPR_REG_VR 16'h0000 |
`define SPR_VERSION_CURRENT 8'h00 |
`define SPR_REG_SR 16'h0011 |
`define SPR_REG_EPCR 16'h0020 |
`define SPR_REG_ESR 16'h0040 |
|
//----------------------------------------------------------------- |
// SR Register bits |
//----------------------------------------------------------------- |
`define OR32_SR_SM 0 |
`define OR32_SR_TEE 1 |
`define OR32_SR_IEE 2 |
`define OR32_SR_DCE 3 |
`define OR32_SR_ICE 4 |
`define OR32_SR_DME 5 |
`define OR32_SR_IME 6 |
`define OR32_SR_LEE 7 |
`define OR32_SR_CE 8 |
`define OR32_SR_F 9 |
`define OR32_SR_CY 10 |
`define OR32_SR_OV 11 |
`define OR32_SR_OVE 12 |
`define OR32_SR_DSX 13 |
`define OR32_SR_EPH 14 |
`define OR32_SR_FO 15 |
`define OR32_SR_TED 16 |
|
//----------------------------------------------------------------- |
// OR32 Vectors |
// NOTE: These differ from the real OR32 vectors for space reasons |
//----------------------------------------------------------------- |
`define VECTOR_RESET 32'h00000100 |
`define VECTOR_ILLEGAL_INST 32'h00000200 |
`define VECTOR_EXTINT 32'h00000300 |
`define VECTOR_SYSCALL 32'h00000400 |
`define VECTOR_TICK_TIMER 32'h00000500 |
`define VECTOR_TRAP 32'h00000600 |
altor32/trunk/rtl/core_pipelined
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property