URL
https://opencores.org/ocsvn/altor32/altor32/trunk
Subversion Repositories altor32
Compare Revisions
- This comparison shows the changes necessary to convert path
/altor32/trunk
- from Rev 33 to Rev 34
- ↔ Reverse comparison
Rev 33 → Rev 34
/rtl/cpu_lite/altor32_regfile_sim.v
0,0 → 1,441
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 - Simulation register file |
//----------------------------------------------------------------- |
module altor32_regfile_sim |
( |
input clk_i /*verilator public*/, |
input rst_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 reg [31:0] reg_rs_o /*verilator public*/, |
output reg [31:0] reg_rt_o /*verilator public*/, |
input [31:0] reg_rd_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// 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; |
|
//----------------------------------------------------------------- |
// 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 |
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 |
|
generate |
if (SUPPORT_32REGS == "ENABLED") |
begin |
// Asynchronous Register read (Rs & Rd) |
always @ * |
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 |
end |
else |
begin |
// Asynchronous Register read (Rs & Rd) |
always @ * |
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; |
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; |
default : |
reg_rt_o = 32'h00000000; |
endcase |
end |
end |
endgenerate |
|
endmodule |
/rtl/cpu_lite/altor32_regfile_xil.v
0,0 → 1,145
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 - Xilinx register file (async read) |
//----------------------------------------------------------------- |
module altor32_regfile_xil |
( |
input clk_i /*verilator public*/, |
input rst_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 reg [31:0] reg_rs_o /*verilator public*/, |
output reg [31:0] reg_rt_o /*verilator public*/, |
input [31:0] reg_rd_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// 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; |
|
//----------------------------------------------------------------- |
// 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 ) |
//----------------------------------------------------------------- |
|
// Registers 0 - 15 |
generate |
begin |
genvar i; |
for (i=0;i<32;i=i+1) |
begin : reg_loop1 |
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 */)); |
end |
end |
endgenerate |
|
// Registers 16 - 31 |
generate |
if (SUPPORT_32REGS == "ENABLED") |
begin |
genvar i; |
for (i=0;i<32;i=i+1) |
begin : reg_loop2 |
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 |
else |
begin |
assign data_out2a = 32'h00000000; |
assign data_out2b = 32'h00000000; |
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 |
/rtl/cpu_lite/altor32_lite.v
0,0 → 1,1547
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 |
//----------------------------------------------------------------- |
|
//`define CONF_CORE_DEBUG |
//`define CONF_CORE_TRACE |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Simple AltOR32 (non-pipelined, small, single WB interface) |
//----------------------------------------------------------------- |
module altor32_lite |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Maskable interrupt |
input intr_i /*verilator public*/, |
|
// Unmaskable interrupt |
input nmi_i /*verilator public*/, |
|
// Enable core |
input enable_i /*verilator public*/, |
|
// Fault |
output reg fault_o /*verilator public*/, |
|
// Breakpoint / Trap |
output reg break_o /*verilator public*/, |
|
// Memory interface |
output reg [31:0] mem_addr_o /*verilator public*/, |
input [31:0] mem_dat_i /*verilator public*/, |
output reg [31:0] mem_dat_o /*verilator public*/, |
output [2:0] mem_cti_o /*verilator public*/, |
output reg mem_cyc_o /*verilator public*/, |
output reg mem_stb_o /*verilator public*/, |
output reg mem_we_o /*verilator public*/, |
output reg [3:0] mem_sel_o /*verilator public*/, |
input mem_stall_i/*verilator public*/, |
input mem_ack_i/*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter BOOT_VECTOR = 32'h00000000; |
parameter ISR_VECTOR = 32'h00000000; |
parameter REGISTER_FILE_TYPE = "SIMULATION"; |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// PC |
reg [31:0] r_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; |
|
// Destination register number (post execute stage) |
reg [4:0] r_e_rd; |
|
// ALU input A |
reg [31:0] r_e_alu_a; |
|
// ALU input B |
reg [31:0] r_e_alu_b; |
|
// ALU output |
wire [31:0] r_e_result; |
|
// ALU Carry |
wire alu_carry_out; |
wire alu_carry_update; |
|
// ALU operation selection |
reg [3:0] r_e_alu_func; |
|
// Delayed NMI |
reg r_nmi; |
|
// SIM PUTC |
`ifdef SIM_EXT_PUTC |
reg [7:0] r_putc; |
`endif |
|
wire [4:0] w_ra; |
wire [4:0] w_rb; |
wire [4:0] w_rd; |
|
wire [31:0] w_reg_ra; |
wire [31:0] w_reg_rb; |
|
reg [31:0] r_opcode; |
|
reg [31:0] r_load_result; |
|
reg [1:0] mem_offset; |
|
// Current state |
parameter STATE_IDLE = 0; |
parameter STATE_FETCH = 1; |
parameter STATE_FETCH_WAIT = 2; |
parameter STATE_EXEC = 3; |
parameter STATE_MEM = 4; |
parameter STATE_WRITE_BACK = 5; |
|
reg [3:0] state; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// ALU |
altor32_alu alu |
( |
// ALU operation select |
.op_i(r_e_alu_func), |
|
// Operands |
.a_i(r_e_alu_a), |
.b_i(r_e_alu_b), |
.c_i(r_sr[`OR32_SR_CY]), |
|
// Result |
.p_o(r_e_result), |
|
// Carry |
.c_o(alu_carry_out), |
.c_update_o(alu_carry_update) |
); |
|
// Writeback result |
wire [31:0] w_write_res = (state == STATE_MEM) ? r_load_result : r_e_result; |
|
// Writeback enable |
wire w_write_en = (state == STATE_MEM & mem_ack_i) | (state == STATE_WRITE_BACK); |
|
// Register file |
generate |
if (REGISTER_FILE_TYPE == "XILINX") |
begin : REGFILE_XIL |
altor32_regfile_xil |
#( |
.SUPPORT_32REGS(SUPPORT_32REGS) |
) |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.wr_i(w_write_en), |
|
// Tri-port |
.rs_i(w_ra), |
.rt_i(w_rb), |
.rd_i(r_e_rd), |
.reg_rs_o(w_reg_ra), |
.reg_rt_o(w_reg_rb), |
.reg_rd_i(w_write_res) |
); |
end |
else if (REGISTER_FILE_TYPE == "ALTERA") |
begin : REGFILE_ALT |
altor32_regfile_alt |
#( |
.SUPPORT_32REGS(SUPPORT_32REGS) |
) |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.wr_i(w_write_en), |
|
// Tri-port |
.rs_i(w_ra), |
.rt_i(w_rb), |
.rd_i(r_e_rd), |
.reg_rs_o(w_reg_ra), |
.reg_rt_o(w_reg_rb), |
.reg_rd_i(w_write_res) |
); |
end |
else |
begin : REGFILE_SIM |
altor32_regfile_sim |
#( |
.SUPPORT_32REGS(SUPPORT_32REGS) |
) |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.wr_i(w_write_en), |
|
// Tri-port |
.rs_i(w_ra), |
.rt_i(w_rb), |
.rd_i(r_e_rd), |
.reg_rs_o(w_reg_ra), |
.reg_rt_o(w_reg_rb), |
.reg_rd_i(w_write_res) |
); |
end |
endgenerate |
|
//----------------------------------------------------------------- |
// Opcode decode |
//----------------------------------------------------------------- |
reg [7:0] inst_r; |
reg [7:0] alu_op_r; |
reg [1:0] shift_op_r; |
reg [15:0] sfxx_op_r; |
reg [15:0] uint16_r; |
reg [31:0] uint32_r; |
reg [31:0] int32_r; |
reg [31:0] store_int32_r; |
reg [15:0] mxspr_uint16_r; |
reg [31:0] target_int26_r; |
reg [31:0] reg_ra_r; |
reg [31:0] reg_rb_r; |
reg [31:0] shift_rb_r; |
reg [31:0] shift_imm_r; |
|
always @ * |
begin |
// Instruction |
inst_r = {2'b00,r_opcode[31:26]}; |
|
// Sub instructions |
alu_op_r = {r_opcode[9:6],r_opcode[3:0]}; |
sfxx_op_r = {5'b00,r_opcode[31:21]}; |
shift_op_r = r_opcode[7:6]; |
|
// Branch target |
target_int26_r = sign_extend_imm26(r_opcode[25:0]); |
|
// Store immediate |
store_int32_r = sign_extend_imm16({r_opcode[25:21],r_opcode[10:0]}); |
|
// Signed & unsigned imm -> 32-bits |
uint16_r = r_opcode[15:0]; |
int32_r = sign_extend_imm16(r_opcode[15:0]); |
uint32_r = extend_imm16(r_opcode[15:0]); |
|
// Register values [ra/rb] |
reg_ra_r = w_reg_ra; |
reg_rb_r = w_reg_rb; |
|
// Shift ammount (from register[rb]) |
shift_rb_r = {26'b00,w_reg_rb[5:0]}; |
|
// Shift ammount (from immediate) |
shift_imm_r = {26'b00,r_opcode[5:0]}; |
|
// MTSPR/MFSPR operand |
mxspr_uint16_r = (w_reg_ra[15:0] | {5'b00000,r_opcode[10:0]}); |
end |
|
//----------------------------------------------------------------- |
// Instruction Decode |
//----------------------------------------------------------------- |
wire inst_add_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADD); // l.add |
wire inst_addc_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADDC); // l.addc |
wire inst_and_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_AND); // l.and |
wire inst_or_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_OR); // l.or |
wire inst_sll_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SLL); // l.sll |
wire inst_sw_ra = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRA); // l.sra |
wire inst_srl_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRL); // l.srl |
wire inst_sub_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SUB); // l.sub |
wire inst_xor_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_XOR); // l.xor |
wire inst_mul_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MUL); // l.mul |
wire inst_mulu_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MULU); // l.mulu |
|
wire inst_addi_w = (inst_r == `INST_OR32_ADDI); // l.addi |
wire inst_andi_w = (inst_r == `INST_OR32_ANDI); // l.andi |
wire inst_bf_w = (inst_r == `INST_OR32_BF); // l.bf |
wire inst_bnf_w = (inst_r == `INST_OR32_BNF); // l.bnf |
wire inst_j_w = (inst_r == `INST_OR32_J); // l.j |
wire inst_jal_w = (inst_r == `INST_OR32_JAL); // l.jal |
wire inst_jalr_w = (inst_r == `INST_OR32_JALR); // l.jalr |
wire inst_jr_w = (inst_r == `INST_OR32_JR); // l.jr |
wire inst_lbs_w = (inst_r == `INST_OR32_LBS); // l.lbs |
wire inst_lhs_w = (inst_r == `INST_OR32_LHS); // l.lhs |
wire inst_lws_w = (inst_r == `INST_OR32_LWS); // l.lws |
wire inst_lbz_w = (inst_r == `INST_OR32_LBZ); // l.lbz |
wire inst_lhz_w = (inst_r == `INST_OR32_LHZ); // l.lhz |
wire inst_lwz_w = (inst_r == `INST_OR32_LWZ); // l.lwz |
wire inst_mfspr_w = (inst_r == `INST_OR32_MFSPR); // l.mfspr |
wire inst_mtspr_w = (inst_r == `INST_OR32_MTSPR); // l.mtspr |
wire inst_movhi_w = (inst_r == `INST_OR32_MOVHI); // l.movhi |
wire inst_nop_w = (inst_r == `INST_OR32_NOP); // l.nop |
wire inst_ori_w = (inst_r == `INST_OR32_ORI); // l.ori |
wire inst_rfe_w = (inst_r == `INST_OR32_RFE); // l.rfe |
|
wire inst_sb_w = (inst_r == `INST_OR32_SB); // l.sb |
wire inst_sh_w = (inst_r == `INST_OR32_SH); // l.sh |
wire inst_sw_w = (inst_r == `INST_OR32_SW); // l.sw |
|
wire inst_slli_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SLLI); // l.slli |
wire inst_srai_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRAI); // l.srai |
wire inst_srli_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRLI); // l.srli |
|
wire inst_xori_w = (inst_r == `INST_OR32_XORI); // l.xori |
|
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX); |
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI); |
|
wire inst_sfeq_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq |
wire inst_sfges_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges |
|
wire inst_sfgeu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu |
wire inst_sfgts_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts |
wire inst_sfgtu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu |
wire inst_sfles_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles |
wire inst_sfleu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu |
wire inst_sflts_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts |
wire inst_sfltu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu |
wire inst_sfne_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne |
|
wire inst_sfeqi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFEQI); // l.sfeqi |
wire inst_sfgesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGESI); // l.sfgesi |
wire inst_sfgeui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGEUI); // l.sfgeui |
wire inst_sfgtsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTSI); // l.sfgtsi |
wire inst_sfgtui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTUI); // l.sfgtui |
wire inst_sflesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLESI); // l.sflesi |
|
wire inst_sfleui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLEUI); // l.sfleui |
wire inst_sfltsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTSI); // l.sfltsi |
wire inst_sfltui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTUI); // l.sfltui |
wire inst_sfnei_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFNEI); // l.sfnei |
|
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_SYS); // l.sys |
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_TRAP); // l.trap |
|
//----------------------------------------------------------------- |
// Load/Store operation? |
//----------------------------------------------------------------- |
reg load_inst_r; |
reg store_inst_r; |
reg [31:0] mem_addr_r; |
always @ * |
begin |
load_inst_r = inst_lbs_w | inst_lhs_w | inst_lws_w | |
inst_lbz_w | inst_lhz_w | inst_lwz_w; |
store_inst_r = inst_sb_w | inst_sh_w | inst_sw_w; |
|
// Memory address is relative to RA |
mem_addr_r = reg_ra_r + (store_inst_r ? store_int32_r : int32_r); |
end |
|
//----------------------------------------------------------------- |
// Next State Logic |
//----------------------------------------------------------------- |
reg [3:0] next_state_r; |
always @ * |
begin |
next_state_r = state; |
|
case (state) |
//----------------------------------------- |
// IDLE - |
//----------------------------------------- |
STATE_IDLE : |
begin |
if (enable_i) |
next_state_r = STATE_FETCH; |
end |
//----------------------------------------- |
// FETCH - Fetch line from memory |
//----------------------------------------- |
STATE_FETCH : |
begin |
next_state_r = STATE_FETCH_WAIT; |
end |
//----------------------------------------- |
// FETCH_WAIT - Wait for read responses |
//----------------------------------------- |
STATE_FETCH_WAIT: |
begin |
// Read from memory complete |
if (mem_ack_i) |
next_state_r = STATE_EXEC; |
end |
//----------------------------------------- |
// EXEC |
//----------------------------------------- |
STATE_EXEC : |
begin |
if (load_inst_r || store_inst_r) |
next_state_r = STATE_MEM; |
else |
next_state_r = STATE_WRITE_BACK; |
end |
//----------------------------------------- |
// MEM |
//----------------------------------------- |
STATE_MEM : |
begin |
// Read from memory complete |
if (mem_ack_i) |
next_state_r = STATE_FETCH; |
end |
//----------------------------------------- |
// WRITE_BACK |
//----------------------------------------- |
STATE_WRITE_BACK : |
begin |
if (enable_i) |
next_state_r = STATE_FETCH; |
end |
default: |
; |
endcase |
end |
|
// Update state |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
state <= STATE_IDLE; |
else |
state <= next_state_r; |
end |
|
//----------------------------------------------------------------- |
// Memory Access / Instruction Fetch |
//----------------------------------------------------------------- |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
mem_addr_o <= 32'h00000000; |
mem_dat_o <= 32'h00000000; |
mem_sel_o <= 4'b0; |
mem_we_o <= 1'b0; |
mem_stb_o <= 1'b0; |
mem_cyc_o <= 1'b0; |
|
r_opcode <= 32'h00000000; |
mem_offset <= 2'b0; |
end |
else |
begin |
|
if (~mem_stall_i) |
mem_stb_o <= 1'b0; |
|
case (state) |
|
//----------------------------------------- |
// FETCH - Issue instruction fetch |
//----------------------------------------- |
STATE_FETCH : |
begin |
// Start fetch from memory |
mem_addr_o <= r_pc; |
mem_stb_o <= 1'b1; |
mem_we_o <= 1'b0; |
mem_cyc_o <= 1'b1; |
end |
//----------------------------------------- |
// FETCH_WAIT - Wait for response |
//----------------------------------------- |
STATE_FETCH_WAIT : |
begin |
// Data ready from memory? |
if (mem_ack_i) |
begin |
r_opcode <= mem_dat_i; |
mem_cyc_o <= 1'b0; |
end |
end |
//----------------------------------------- |
// EXEC - Issue read / write |
//----------------------------------------- |
STATE_EXEC : |
begin |
`ifdef CONF_CORE_TRACE |
$display("%08x: Execute 0x%08x", r_pc, r_opcode); |
$display(" rA[%d] = 0x%08x", w_ra, reg_ra_r); |
$display(" rB[%d] = 0x%08x", w_rb, reg_rb_r); |
`endif |
|
case (1'b1) |
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz |
load_inst_r: |
begin |
mem_addr_o <= {mem_addr_r[31:2], 2'b0}; |
mem_offset <= mem_addr_r[1:0]; |
mem_dat_o <= 32'h00000000; |
mem_sel_o <= 4'b1111; |
mem_we_o <= 1'b0; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Load from 0x%08x to R%d", mem_addr_r, w_rd); |
`endif |
end |
|
inst_sb_w: // l.sb |
begin |
mem_addr_o <= {mem_addr_r[31:2], 2'b0}; |
mem_offset <= mem_addr_r[1:0]; |
case (mem_addr_r[1:0]) |
2'b00 : |
begin |
mem_dat_o <= {reg_rb_r[7:0],24'h000000}; |
mem_sel_o <= 4'b1000; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
end |
2'b01 : |
begin |
mem_dat_o <= {{8'h00,reg_rb_r[7:0]},16'h0000}; |
mem_sel_o <= 4'b0100; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
end |
2'b10 : |
begin |
mem_dat_o <= {{16'h0000,reg_rb_r[7:0]},8'h00}; |
mem_sel_o <= 4'b0010; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
end |
2'b11 : |
begin |
mem_dat_o <= {24'h000000,reg_rb_r[7:0]}; |
mem_sel_o <= 4'b0001; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
end |
default : |
; |
endcase |
end |
|
inst_sh_w: // l.sh |
begin |
mem_addr_o <= {mem_addr_r[31:2], 2'b0}; |
mem_offset <= mem_addr_r[1:0]; |
case (mem_addr_r[1:0]) |
2'b00 : |
begin |
mem_dat_o <= {reg_rb_r[15:0],16'h0000}; |
mem_sel_o <= 4'b1100; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
end |
2'b10 : |
begin |
mem_dat_o <= {16'h0000,reg_rb_r[15:0]}; |
mem_sel_o <= 4'b0011; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
end |
default : |
; |
endcase |
end |
|
inst_sw_w: // l.sw |
begin |
mem_addr_o <= {mem_addr_r[31:2], 2'b0}; |
mem_offset <= mem_addr_r[1:0]; |
mem_dat_o <= reg_rb_r; |
mem_sel_o <= 4'b1111; |
mem_we_o <= 1'b1; |
mem_stb_o <= 1'b1; |
mem_cyc_o <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Store R%d to 0x%08x = 0x%08x", w_rb, {mem_addr_r[31:2],2'b00}, reg_rb_r); |
`endif |
end |
default: |
; |
endcase |
end |
//----------------------------------------- |
// MEM - Wait for response |
//----------------------------------------- |
STATE_MEM : |
begin |
// Data ready from memory? |
if (mem_ack_i) |
begin |
mem_cyc_o <= 1'b0; |
end |
end |
default: |
; |
endcase |
end |
end |
|
assign mem_cti_o = 3'b111; |
|
// If simulation, RA = 03 if NOP instruction |
`ifdef SIMULATION |
wire [7:0] v_fetch_inst = {2'b00, r_opcode[31:26]}; |
wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP); |
assign w_ra = v_is_nop ? 5'd3 : r_opcode[20:16]; |
`else |
assign w_ra = r_opcode[20:16]; |
`endif |
|
assign w_rb = r_opcode[15:11]; |
assign w_rd = r_opcode[25:21]; |
|
//----------------------------------------------------------------- |
// Next PC |
//----------------------------------------------------------------- |
reg [31:0] next_pc_r; |
|
always @ * |
begin |
// Next expected PC (current PC + 4) |
next_pc_r = (r_pc + 4); |
end |
|
//----------------------------------------------------------------- |
// Next SR |
//----------------------------------------------------------------- |
reg [31:0] next_sr_r; |
reg compare_result_r; |
always @ * |
begin |
next_sr_r = r_sr; |
|
// Latch carry if updated |
if (alu_carry_update) |
next_sr_r[`OR32_SR_CY] = alu_carry_out; |
|
case (1'b1) |
inst_mtspr_w: |
begin |
case (mxspr_uint16_r) |
// SR - Supervision register |
`SPR_REG_SR: |
begin |
next_sr_r[`OR32_SR_F] = reg_rb_r[`OR32_SR_F]; |
next_sr_r[`OR32_SR_CY] = reg_rb_r[`OR32_SR_CY]; |
next_sr_r[`OR32_SR_IEE] = reg_rb_r[`OR32_SR_IEE]; |
end |
default: |
; |
endcase |
end |
inst_rfe_w: |
begin |
next_sr_r[`OR32_SR_F] = r_esr[`OR32_SR_F]; |
next_sr_r[`OR32_SR_CY] = r_esr[`OR32_SR_CY]; |
next_sr_r[`OR32_SR_IEE] = r_esr[`OR32_SR_IEE]; |
end |
inst_sfxx_w, |
inst_sfxxi_w: |
next_sr_r[`OR32_SR_F] = compare_result_r; |
default: |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Next EPC/ESR |
//----------------------------------------------------------------- |
reg [31:0] next_epc_r; |
reg [31:0] next_esr_r; |
|
always @ * |
begin |
next_epc_r = r_epc; |
next_esr_r = r_esr; |
|
case (1'b1) |
inst_mtspr_w: // l.mtspr |
begin |
case (mxspr_uint16_r) |
// EPCR - EPC Exception saved PC |
`SPR_REG_EPCR: next_epc_r = reg_rb_r; |
|
// ESR - Exception saved SR |
`SPR_REG_ESR: next_esr_r = reg_rb_r; |
endcase |
end |
default: |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// ALU inputs |
//----------------------------------------------------------------- |
|
// ALU operation selection |
reg [3:0] alu_func_r; |
|
// ALU operands |
reg [31:0] alu_input_a_r; |
reg [31:0] alu_input_b_r; |
reg write_rd_r; |
|
always @ * |
begin |
alu_func_r = `ALU_NONE; |
alu_input_a_r = 32'b0; |
alu_input_b_r = 32'b0; |
write_rd_r = 1'b0; |
|
case (1'b1) |
|
inst_add_w: // l.add |
begin |
alu_func_r = `ALU_ADD; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = reg_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_addc_w: // l.addc |
begin |
alu_func_r = `ALU_ADDC; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = reg_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_and_w: // l.and |
begin |
alu_func_r = `ALU_AND; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = reg_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_or_w: // l.or |
begin |
alu_func_r = `ALU_OR; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = reg_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_sll_w: // l.sll |
begin |
alu_func_r = `ALU_SHIFTL; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = shift_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_sw_ra: // l.sra |
begin |
alu_func_r = `ALU_SHIRTR_ARITH; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = shift_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_srl_w: // l.srl |
begin |
alu_func_r = `ALU_SHIFTR; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = shift_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_sub_w: // l.sub |
begin |
alu_func_r = `ALU_SUB; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = reg_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_xor_w: // l.xor |
begin |
alu_func_r = `ALU_XOR; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = reg_rb_r; |
write_rd_r = 1'b1; |
end |
|
inst_mul_w, // l.mul |
inst_mulu_w: // l.mulu |
begin |
write_rd_r = 1'b1; |
end |
|
inst_addi_w: // l.addi |
begin |
alu_func_r = `ALU_ADD; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = int32_r; |
write_rd_r = 1'b1; |
end |
|
inst_andi_w: // l.andi |
begin |
alu_func_r = `ALU_AND; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = uint32_r; |
write_rd_r = 1'b1; |
end |
|
inst_jal_w: // l.jal |
begin |
alu_input_a_r = next_pc_r; |
write_rd_r = 1'b1; |
end |
|
inst_jalr_w: // l.jalr |
begin |
alu_input_a_r = next_pc_r; |
write_rd_r = 1'b1; |
end |
|
inst_mfspr_w: // l.mfspr |
begin |
case (mxspr_uint16_r) |
// SR - Supervision register |
`SPR_REG_SR: |
begin |
alu_input_a_r = 32'b0; |
alu_input_a_r[`OR32_SR_F] = next_sr_r[`OR32_SR_F]; |
alu_input_a_r[`OR32_SR_CY] = next_sr_r[`OR32_SR_CY]; |
alu_input_a_r[`OR32_SR_IEE] = next_sr_r[`OR32_SR_IEE]; |
write_rd_r = 1'b1; |
end |
|
// EPCR - EPC Exception saved PC |
`SPR_REG_EPCR: |
begin |
alu_input_a_r = r_epc; |
write_rd_r = 1'b1; |
end |
|
// ESR - Exception saved SR |
`SPR_REG_ESR: |
begin |
alu_input_a_r = 32'b0; |
alu_input_a_r[`OR32_SR_F] = r_esr[`OR32_SR_F]; |
alu_input_a_r[`OR32_SR_CY] = r_esr[`OR32_SR_CY]; |
alu_input_a_r[`OR32_SR_IEE] = r_esr[`OR32_SR_IEE]; |
write_rd_r = 1'b1; |
end |
default: |
; |
endcase |
end |
|
inst_movhi_w: // l.movhi |
begin |
alu_input_a_r = {uint16_r,16'h0000}; |
write_rd_r = 1'b1; |
end |
|
inst_ori_w: // l.ori |
begin |
alu_func_r = `ALU_OR; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = uint32_r; |
write_rd_r = 1'b1; |
end |
|
inst_slli_w: // l.slli |
begin |
alu_func_r = `ALU_SHIFTL; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = shift_imm_r; |
write_rd_r = 1'b1; |
end |
|
inst_srai_w: // l.srai |
begin |
alu_func_r = `ALU_SHIRTR_ARITH; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = shift_imm_r; |
write_rd_r = 1'b1; |
end |
|
inst_srli_w: // l.srli |
begin |
alu_func_r = `ALU_SHIFTR; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = shift_imm_r; |
write_rd_r = 1'b1; |
end |
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz |
inst_lbs_w, |
inst_lhs_w, |
inst_lws_w, |
inst_lbz_w, |
inst_lhz_w, |
inst_lwz_w: |
write_rd_r = 1'b1; |
|
inst_xori_w: // l.xori |
begin |
alu_func_r = `ALU_XOR; |
alu_input_a_r = reg_ra_r; |
alu_input_b_r = int32_r; |
write_rd_r = 1'b1; |
end |
default: |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Comparisons |
//----------------------------------------------------------------- |
|
reg [31:0] compare_a_r; |
reg [31:0] compare_b_r; |
always @ * |
begin |
compare_a_r = reg_ra_r; |
compare_b_r = reg_rb_r; |
|
case (1'b1) |
inst_sfeqi_w, // l.sfeqi |
inst_sfgesi_w, // l.sfgesi |
inst_sfgeui_w, // l.sfgeui |
inst_sfgtsi_w, // l.sfgtsi |
inst_sfgtui_w, // l.sfgtui |
inst_sflesi_w, // l.sflesi |
inst_sfleui_w, // l.sfleui |
inst_sfltsi_w, // l.sfltsi |
inst_sfltui_w, // l.sfltui |
inst_sfnei_w: // l.sfnei |
compare_b_r = int32_r; |
default: |
; |
endcase |
end |
|
reg compare_equal_r; |
reg compare_gts_r; |
reg compare_gt_r; |
reg compare_lts_r; |
reg compare_lt_r; |
always @ * |
begin |
if (compare_a_r == compare_b_r) |
compare_equal_r = 1'b1; |
else |
compare_equal_r = 1'b0; |
|
compare_lts_r = less_than_signed(compare_a_r, compare_b_r); |
|
if (compare_a_r < compare_b_r) |
compare_lt_r = 1'b1; |
else |
compare_lt_r = 1'b0; |
|
// Greater than (signed) |
compare_gts_r = ~(compare_lts_r | compare_equal_r); |
|
if (compare_a_r > compare_b_r) |
compare_gt_r = 1'b1; |
else |
compare_gt_r = 1'b0; |
end |
|
always @ * |
begin |
compare_result_r = 1'b0; |
|
case (1'b1) |
inst_sfeq_w, // l.sfeq |
inst_sfeqi_w: // l.sfeqi |
compare_result_r = compare_equal_r; |
|
inst_sfges_w, // l.sfges |
inst_sfgesi_w: // l.sfgesi |
compare_result_r = compare_gts_r | compare_equal_r; |
|
inst_sfgeu_w, // l.sfgeu |
inst_sfgeui_w: // l.sfgeui |
compare_result_r = compare_gt_r | compare_equal_r; |
|
inst_sfgts_w, // l.sfgts |
inst_sfgtsi_w: // l.sfgtsi |
compare_result_r = compare_gts_r; |
|
inst_sfgtu_w, // l.sfgtu |
inst_sfgtui_w: // l.sfgtui |
compare_result_r = compare_gt_r; |
|
inst_sfles_w, // l.sfles |
inst_sflesi_w: // l.sflesi |
compare_result_r = compare_lts_r | compare_equal_r; |
|
inst_sfleu_w, // l.sfleu |
inst_sfleui_w: // l.sfleui |
compare_result_r = compare_lt_r | compare_equal_r; |
|
inst_sflts_w, // l.sflts |
inst_sfltsi_w: // l.sfltsi |
compare_result_r = compare_lts_r; |
|
inst_sfltu_w, // l.sfltu |
inst_sfltui_w: // l.sfltui |
compare_result_r = compare_lt_r; |
|
inst_sfne_w, // l.sfne |
inst_sfnei_w: // l.sfnei |
compare_result_r = ~compare_equal_r; |
|
default: |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Branches |
//----------------------------------------------------------------- |
reg branch_r; |
reg branch_link_r; |
reg [31:0] branch_target_r; |
reg branch_except_r; |
|
always @ * |
begin |
|
branch_r = 1'b0; |
branch_link_r = 1'b0; |
branch_except_r = 1'b0; |
|
// Default branch target is relative to current PC |
branch_target_r = (r_pc + {target_int26_r[29:0],2'b00}); |
|
case (1'b1) |
inst_bf_w: // l.bf |
branch_r = r_sr[`OR32_SR_F]; |
|
inst_bnf_w: // l.bnf |
branch_r = ~r_sr[`OR32_SR_F]; |
|
inst_j_w: // l.j |
branch_r = 1'b1; |
|
inst_jal_w: // l.jal |
begin |
// Write to REG_9_LR |
branch_link_r = 1'b1; |
branch_r = 1'b1; |
end |
|
inst_jalr_w: // l.jalr |
begin |
// Write to REG_9_LR |
branch_link_r = 1'b1; |
branch_r = 1'b1; |
branch_target_r = reg_rb_r; |
end |
|
inst_jr_w: // l.jr |
begin |
branch_r = 1'b1; |
branch_target_r = reg_rb_r; |
end |
|
inst_rfe_w: // l.rfe |
begin |
branch_r = 1'b1; |
branch_target_r = r_epc; |
end |
|
inst_sys_w: // l.sys |
begin |
branch_r = 1'b1; |
branch_except_r = 1'b1; |
branch_target_r = ISR_VECTOR + `VECTOR_SYSCALL; |
end |
|
inst_trap_w: // l.trap |
begin |
branch_r = 1'b1; |
branch_except_r = 1'b1; |
branch_target_r = ISR_VECTOR + `VECTOR_TRAP; |
end |
|
default: |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Invalid instruction |
//----------------------------------------------------------------- |
reg invalid_inst_r; |
|
always @ * |
begin |
case (1'b1) |
inst_add_w, |
inst_addc_w, |
inst_and_w, |
inst_or_w, |
inst_sll_w, |
inst_sw_ra, |
inst_srl_w, |
inst_sub_w, |
inst_xor_w, |
inst_addi_w, |
inst_andi_w, |
inst_bf_w, |
inst_bnf_w, |
inst_j_w, |
inst_jal_w, |
inst_jalr_w, |
inst_jr_w, |
inst_lbs_w, |
inst_lhs_w, |
inst_lws_w, |
inst_lbz_w, |
inst_lhz_w, |
inst_lwz_w, |
inst_mfspr_w, |
inst_mtspr_w, |
inst_movhi_w, |
inst_nop_w, |
inst_ori_w, |
inst_rfe_w, |
inst_sb_w, |
inst_sh_w, |
inst_sw_w, |
inst_xori_w, |
inst_slli_w, |
inst_srai_w, |
inst_srli_w, |
inst_sfeq_w, |
inst_sfeqi_w, |
inst_sfges_w, |
inst_sfgesi_w, |
inst_sfgeu_w, |
inst_sfgeui_w, |
inst_sfgts_w, |
inst_sfgtsi_w, |
inst_sfgtu_w, |
inst_sfgtui_w, |
inst_sfles_w, |
inst_sflesi_w, |
inst_sfleu_w, |
inst_sfleui_w, |
inst_sflts_w, |
inst_sfltsi_w, |
inst_sfltu_w, |
inst_sfltui_w, |
inst_sfne_w, |
inst_sfnei_w, |
inst_sys_w, |
inst_trap_w: |
invalid_inst_r = 1'b0; |
default: |
invalid_inst_r = 1'b1; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Execute: ALU control |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
r_e_alu_func <= `ALU_NONE; |
r_e_alu_a <= 32'h00000000; |
r_e_alu_b <= 32'h00000000; |
r_e_rd <= 5'b00000; |
end |
else |
begin |
// Update ALU input flops |
r_e_alu_func <= alu_func_r; |
r_e_alu_a <= alu_input_a_r; |
r_e_alu_b <= alu_input_b_r; |
|
// Branch and link (Rd = LR/R9) |
if (branch_link_r) |
r_e_rd <= 5'd9; |
// Instruction with register writeback |
else if (write_rd_r) |
r_e_rd <= w_rd; |
else |
r_e_rd <= 5'b0; |
end |
end |
|
//----------------------------------------------------------------- |
// Execute: Branch / exceptions |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
r_pc <= BOOT_VECTOR + `VECTOR_RESET; |
|
// Status registers |
r_epc <= 32'h00000000; |
r_sr <= 32'h00000000; |
r_esr <= 32'h00000000; |
|
fault_o <= 1'b0; |
|
r_nmi <= 1'b0; |
end |
else |
begin |
// Record NMI in-case it can't be processed this cycle |
if (nmi_i) |
r_nmi <= 1'b1; |
|
// Core disabled? |
if (~enable_i) |
begin |
// Reset |
r_pc <= BOOT_VECTOR + `VECTOR_RESET; |
|
// Status registers |
r_epc <= 32'h00000000; |
r_sr <= 32'h00000000; |
r_esr <= 32'h00000000; |
|
fault_o <= 1'b0; |
|
r_nmi <= 1'b0; |
end |
// Write-back? |
else if (w_write_en) |
begin |
// Update SR |
r_sr <= next_sr_r; |
|
// Exception: Instruction opcode not valid / supported, invalid PC |
if (invalid_inst_r || (r_pc[1:0] != 2'b00)) |
begin |
// Save PC of next instruction |
r_epc <= next_pc_r; |
r_esr <= next_sr_r; |
|
// Disable further interrupts |
r_sr <= 32'b0; |
|
// Set PC to exception vector |
if (invalid_inst_r) |
r_pc <= ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
else |
r_pc <= ISR_VECTOR + `VECTOR_BUS_ERROR; |
|
fault_o <= 1'b1; |
end |
// Exception: Syscall / Break |
else if (branch_except_r) |
begin |
// Save PC of next instruction |
r_epc <= next_pc_r; |
r_esr <= next_sr_r; |
|
// Disable further interrupts |
r_sr <= 32'b0; |
|
// Set PC to exception vector |
r_pc <= branch_target_r; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Exception 0x%08x", branch_target_r); |
`endif |
end |
// Non-maskable interrupt |
else if (nmi_i | r_nmi) |
begin |
r_nmi <= 1'b0; |
|
// Save PC of next instruction |
if (branch_r) |
r_epc <= branch_target_r; |
// Next expected PC (current PC + 4) |
else |
r_epc <= next_pc_r; |
|
r_esr <= next_sr_r; |
|
// Disable further interrupts |
r_sr <= 32'b0; |
|
// Set PC to exception vector |
r_pc <= ISR_VECTOR + `VECTOR_NMI; |
|
`ifdef CONF_CORE_DEBUG |
$display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI); |
`endif |
end |
// External interrupt |
else if (intr_i && next_sr_r[`OR32_SR_IEE]) |
begin |
// Save PC of next instruction & SR |
if (branch_r) |
r_epc <= branch_target_r; |
// Next expected PC (current PC + 4) |
else |
r_epc <= next_pc_r; |
|
r_esr <= next_sr_r; |
|
// Disable further interrupts |
r_sr <= 32'b0; |
|
// Set PC to external interrupt vector |
r_pc <= ISR_VECTOR + `VECTOR_EXTINT; |
|
`ifdef CONF_CORE_DEBUG |
$display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT); |
`endif |
end |
// Branch (l.bf, l.bnf, l.j, l.jal, l.jr, l.jalr, l.rfe) |
else if (branch_r) |
begin |
// Perform branch |
r_pc <= branch_target_r; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Branch to 0x%08x", branch_target_r); |
`endif |
end |
// Non branch |
else |
begin |
// Update EPC / ESR which may have been updated |
// by an MTSPR write |
r_pc <= next_pc_r; |
r_epc <= next_epc_r; |
r_esr <= next_esr_r; |
end |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Load result |
//------------------------------------------------------------------- |
always @ * |
begin |
r_load_result = 32'h00000000; |
|
case (1'b1) |
|
inst_lbs_w, // l.lbs |
inst_lbz_w: // l.lbz |
begin |
case (mem_offset) |
2'b00 : r_load_result[7:0] = mem_dat_i[31:24]; |
2'b01 : r_load_result[7:0] = mem_dat_i[23:16]; |
2'b10 : r_load_result[7:0] = mem_dat_i[15:8]; |
2'b11 : r_load_result[7:0] = mem_dat_i[7:0]; |
default : ; |
endcase |
|
// Sign extend LB |
if (inst_lbs_w && r_load_result[7]) |
r_load_result[31:8] = 24'hFFFFFF; |
end |
|
inst_lhs_w, // l.lhs |
inst_lhz_w: // l.lhz |
begin |
case (mem_offset) |
2'b00 : r_load_result[15:0] = mem_dat_i[31:16]; |
2'b10 : r_load_result[15:0] = mem_dat_i[15:0]; |
default : ; |
endcase |
|
// Sign extend LH |
if (inst_lhs_w && r_load_result[15]) |
r_load_result[31:16] = 16'hFFFF; |
end |
|
// l.lwz l.lws |
default : |
r_load_result = mem_dat_i; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Execute: Misc operations |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
break_o <= 1'b0; |
end |
else |
begin |
break_o <= 1'b0; |
|
case (1'b1) |
inst_trap_w: // l.trap |
break_o <= 1'b1; |
default: |
; |
endcase |
end |
end |
|
//----------------------------------------------------------------- |
// Execute: NOP (simulation) operations |
//----------------------------------------------------------------- |
`ifdef SIMULATION |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
`ifdef SIM_EXT_PUTC |
r_putc <= 8'b0; |
`endif |
end |
else |
begin |
`ifdef SIM_EXT_PUTC |
r_putc <= 8'b0; |
`endif |
if (inst_nop_w && state == STATE_EXEC) |
begin |
case (uint16_r) |
// NOP_PUTC |
16'h0004: |
begin |
`ifdef SIM_EXT_PUTC |
r_putc <= reg_ra_r[7:0]; |
`else |
$write("%c", reg_ra_r[7:0]); |
`endif |
end |
// NOP |
16'h0000: ; |
endcase |
end |
end |
end |
`endif |
|
`include "altor32_funcs.v" |
|
//------------------------------------------------------------------- |
// Hooks for debug |
//------------------------------------------------------------------- |
`ifdef verilator |
function [31:0] get_opcode_ex; |
// verilator public |
get_opcode_ex = (state == STATE_EXEC) ? r_opcode : `OPCODE_INST_BUBBLE; |
endfunction |
function [31:0] get_pc_ex; |
// verilator public |
get_pc_ex = r_pc; |
endfunction |
function [7:0] get_putc; |
// verilator public |
`ifdef SIM_EXT_PUTC |
get_putc = r_putc; |
`else |
get_putc = 8'b0; |
`endif |
endfunction |
function [0:0] get_reg_valid; |
// verilator public |
get_reg_valid = (state == STATE_EXEC) ? 1'b1 : 1'b0; |
endfunction |
function [4:0] get_reg_ra; |
// verilator public |
get_reg_ra = w_ra; |
endfunction |
function [31:0] get_reg_ra_value; |
// verilator public |
get_reg_ra_value = w_reg_ra; |
endfunction |
function [4:0] get_reg_rb; |
// verilator public |
get_reg_rb = w_rb; |
endfunction |
function [31:0] get_reg_rb_value; |
// verilator public |
get_reg_rb_value = w_reg_rb; |
endfunction |
`endif |
|
endmodule |
/rtl/cpu_lite/altor32_regfile_alt.v
0,0 → 1,195
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 - Altera LPM register file |
//----------------------------------------------------------------- |
module altor32_regfile_alt |
( |
input clk_i /*verilator public*/, |
input rst_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*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg clk_delayed; |
wire [31:0] data_out1; |
wire [31:0] data_out2; |
reg write_enable; |
|
reg [31:0] reg_rs_o; |
reg [31:0] reg_rt_o; |
|
reg [4:0] addr_reg; |
reg [31:0] data_reg; |
|
wire [31:0] q1; |
wire [31:0] q2; |
|
//----------------------------------------------------------------- |
// 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? |
if ((rd_i != 5'b00000) & (wr_i == 1'b1)) |
write_enable <= 1'b1; |
else |
write_enable <= 1'b0; |
end |
|
//----------------------------------------------------------------- |
// Sync addr & data |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
addr_reg <= 5'b00000; |
data_reg <= 32'h00000000; |
|
end |
else |
begin |
addr_reg <= rd_i; |
data_reg <= reg_rd_i; |
end |
end |
|
//----------------------------------------------------------------- |
// Register File (using lpm_ram_dp) |
// Unfortunatly, LPM_RAM_DP primitives have synchronous read ports. |
// As this core requires asynchronous/non-registered read ports, |
// we have to invert the readclock edge to get close to what we |
// require. |
// This will have negative timing implications! |
//----------------------------------------------------------------- |
lpm_ram_dp |
#( |
.lpm_width(32), |
.lpm_widthad(5), |
.lpm_indata("REGISTERED"), |
.lpm_outdata("UNREGISTERED"), |
.lpm_rdaddress_control("REGISTERED"), |
.lpm_wraddress_control("REGISTERED"), |
.lpm_file("UNUSED"), |
.lpm_type("lpm_ram_dp"), |
.lpm_hint("UNUSED") |
) |
lpm1 |
( |
.rdclock(clk_delayed), |
.rdclken(1'b1), |
.rdaddress(rs_i), |
.rden(1'b1), |
.data(reg_rd_i), |
.wraddress(rd_i), |
.wren(write_enable), |
.wrclock(clk_i), |
.wrclken(1'b1), |
.q(q1) |
); |
|
|
lpm_ram_dp |
#( |
.lpm_width(32), |
.lpm_widthad(5), |
.lpm_indata("REGISTERED"), |
.lpm_outdata("UNREGISTERED"), |
.lpm_rdaddress_control("REGISTERED"), |
.lpm_wraddress_control("REGISTERED"), |
.lpm_file("UNUSED"), |
.lpm_type("lpm_ram_dp"), |
.lpm_hint("UNUSED") |
) |
lpm2 |
( |
.rdclock(clk_delayed), |
.rdclken(1'b1), |
.rdaddress(rt_i), |
.rden(1'b1), |
.data(reg_rd_i), |
.wraddress(rd_i), |
.wren(write_enable), |
.wrclock(clk_i), |
.wrclken(1'b1), |
.q(q2) |
); |
|
//----------------------------------------------------------------- |
// Combinatorial Assignments |
//----------------------------------------------------------------- |
|
// Delayed clock |
assign clk_delayed = !clk_i; |
|
// Reads are bypassed during write-back |
assign data_out1 = (rs_i != addr_reg) ? q1 : data_reg; |
assign data_out2 = (rt_i != addr_reg) ? q2 : data_reg; |
|
endmodule |
/rtl/cpu_lite/altor32_funcs.v
0,0 → 1,253
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// 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 |
|
//----------------------------------------------------------------- |
// is_load_operation: Is this opcode a load operation? |
// Inputs: opcode |
// Return: 1 or 0 |
//----------------------------------------------------------------- |
function [0:0] is_load_operation; |
input [7:0] opcode; |
begin |
is_load_operation = (opcode == `INST_OR32_LBS || |
opcode == `INST_OR32_LBZ || |
opcode == `INST_OR32_LHS || |
opcode == `INST_OR32_LHZ || |
opcode == `INST_OR32_LWZ || |
opcode == `INST_OR32_LWS) ? 1'b1 : 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// is_store_operation: Is this opcode a store operation? |
// Inputs: opcode |
// Return: 1 or 0 |
//----------------------------------------------------------------- |
function [0:0] is_store_operation; |
input [7:0] opcode; |
begin |
is_store_operation = (opcode == `INST_OR32_SB || |
opcode == `INST_OR32_SH || |
opcode == `INST_OR32_SW) ? 1'b1 : 1'b0; |
end |
endfunction |
/rtl/cpu_lite/altor32.v
0,0 → 1,130
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module - Simple AltOR32 (wrapper for cutdown core) |
//----------------------------------------------------------------- |
module cpu |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Maskable interrupt |
input intr_i /*verilator public*/, |
|
// Unmaskable interrupt |
input nmi_i /*verilator public*/, |
|
// Fault |
output fault_o /*verilator public*/, |
|
// Breakpoint / Trap |
output break_o /*verilator public*/, |
|
// Instruction memory (unused) |
output [31:0] imem_addr_o /*verilator public*/, |
input [31:0] imem_dat_i /*verilator public*/, |
output [2:0] imem_cti_o /*verilator public*/, |
output imem_cyc_o /*verilator public*/, |
output imem_stb_o /*verilator public*/, |
input imem_stall_i/*verilator public*/, |
input imem_ack_i/*verilator public*/, |
|
// Memory interface |
output [31:0] dmem_addr_o /*verilator public*/, |
input [31:0] dmem_dat_i /*verilator public*/, |
output [31:0] dmem_dat_o /*verilator public*/, |
output [2:0] dmem_cti_o /*verilator public*/, |
output dmem_cyc_o /*verilator public*/, |
output dmem_stb_o /*verilator public*/, |
output dmem_we_o /*verilator public*/, |
output [3:0] dmem_sel_o /*verilator public*/, |
input dmem_stall_i/*verilator public*/, |
input dmem_ack_i/*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter BOOT_VECTOR = 32'h00000000; |
parameter ISR_VECTOR = 32'h00000000; |
parameter REGISTER_FILE_TYPE = "SIMULATION"; |
parameter ENABLE_ICACHE = "DISABLED"; // Unused |
parameter ENABLE_DCACHE = "DISABLED"; // Unused |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
// CPU |
altor32_lite |
#( |
.BOOT_VECTOR(BOOT_VECTOR), |
.ISR_VECTOR(ISR_VECTOR), |
.REGISTER_FILE_TYPE(REGISTER_FILE_TYPE) |
) |
u_exec |
( |
// General - clocking & reset |
.clk_i(clk_i), |
.rst_i(rst_i), |
.fault_o(fault_o), |
.break_o(break_o), |
.nmi_i(nmi_i), |
.intr_i(intr_i), |
.enable_i(1'b1), |
|
.mem_addr_o(dmem_addr_o), |
.mem_dat_o(dmem_dat_o), |
.mem_dat_i(dmem_dat_i), |
.mem_sel_o(dmem_sel_o), |
.mem_cti_o(dmem_cti_o), |
.mem_cyc_o(dmem_cyc_o), |
.mem_we_o(dmem_we_o), |
.mem_stb_o(dmem_stb_o), |
.mem_stall_i(dmem_stall_i), |
.mem_ack_i(dmem_ack_i) |
); |
|
// Unused outputs |
assign imem_addr_o = 32'b0; |
assign imem_cti_o = 3'b0; |
assign imem_cyc_o = 1'b0; |
assign imem_stb_o = 1'b0; |
|
endmodule |
/rtl/cpu_lite/altor32_alu.v
0,0 → 1,209
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 - ALU |
//----------------------------------------------------------------- |
module altor32_alu |
( |
// ALU operation select |
input [3:0] op_i /*verilator public*/, |
|
// Operands |
input [31:0] a_i /*verilator public*/, |
input [31:0] b_i /*verilator public*/, |
input c_i /*verilator public*/, |
|
// Result |
output [31:0] p_o /*verilator public*/, |
|
// Carry |
output reg c_o /*verilator public*/, |
output reg c_update_o /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [31:0] result; |
|
reg [31:16] shift_right_fill; |
reg [31:0] shift_right_1; |
reg [31:0] shift_right_2; |
reg [31:0] shift_right_4; |
reg [31:0] shift_right_8; |
|
reg [31:0] shift_left_1; |
reg [31:0] shift_left_2; |
reg [31:0] shift_left_4; |
reg [31:0] shift_left_8; |
|
//----------------------------------------------------------------- |
// ALU |
//----------------------------------------------------------------- |
always @ (op_i or a_i or b_i or c_i) |
begin |
case (op_i) |
//---------------------------------------------- |
// Shift Left |
//---------------------------------------------- |
`ALU_SHIFTL : |
begin |
if (b_i[0] == 1'b1) |
shift_left_1 = {a_i[30:0],1'b0}; |
else |
shift_left_1 = a_i; |
|
if (b_i[1] == 1'b1) |
shift_left_2 = {shift_left_1[29:0],2'b00}; |
else |
shift_left_2 = shift_left_1; |
|
if (b_i[2] == 1'b1) |
shift_left_4 = {shift_left_2[27:0],4'b0000}; |
else |
shift_left_4 = shift_left_2; |
|
if (b_i[3] == 1'b1) |
shift_left_8 = {shift_left_4[23:0],8'b00000000}; |
else |
shift_left_8 = shift_left_4; |
|
if (b_i[4] == 1'b1) |
result = {shift_left_8[15:0],16'b0000000000000000}; |
else |
result = shift_left_8; |
|
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
//---------------------------------------------- |
// Shift Right |
//---------------------------------------------- |
`ALU_SHIFTR, `ALU_SHIRTR_ARITH: |
begin |
// Arithmetic shift? Fill with 1's if MSB set |
if (a_i[31] == 1'b1 && op_i == `ALU_SHIRTR_ARITH) |
shift_right_fill = 16'b1111111111111111; |
else |
shift_right_fill = 16'b0000000000000000; |
|
if (b_i[0] == 1'b1) |
shift_right_1 = {shift_right_fill[31], a_i[31:1]}; |
else |
shift_right_1 = a_i; |
|
if (b_i[1] == 1'b1) |
shift_right_2 = {shift_right_fill[31:30], shift_right_1[31:2]}; |
else |
shift_right_2 = shift_right_1; |
|
if (b_i[2] == 1'b1) |
shift_right_4 = {shift_right_fill[31:28], shift_right_2[31:4]}; |
else |
shift_right_4 = shift_right_2; |
|
if (b_i[3] == 1'b1) |
shift_right_8 = {shift_right_fill[31:24], shift_right_4[31:8]}; |
else |
shift_right_8 = shift_right_4; |
|
if (b_i[4] == 1'b1) |
result = {shift_right_fill[31:16], shift_right_8[31:16]}; |
else |
result = shift_right_8; |
|
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
//---------------------------------------------- |
// Arithmetic |
//---------------------------------------------- |
`ALU_ADD : |
begin |
{c_o, result} = (a_i + b_i); |
c_update_o = 1'b1; |
end |
`ALU_ADDC : |
begin |
{c_o, result} = (a_i + b_i) + {31'h00000000, c_i}; |
c_update_o = 1'b1; |
end |
`ALU_SUB : |
begin |
result = (a_i - b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
//---------------------------------------------- |
// Logical |
//---------------------------------------------- |
`ALU_AND : |
begin |
result = (a_i & b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
`ALU_OR : |
begin |
result = (a_i | b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
`ALU_XOR : |
begin |
result = (a_i ^ b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
default : |
begin |
result = a_i; |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
endcase |
end |
|
assign p_o = result; |
|
endmodule |
/rtl/cpu_lite/altor32_defs.v
0,0 → 1,186
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 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 |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// 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_ADDC 4'b0101 |
`define ALU_SUB 4'b0110 |
`define ALU_AND 4'b0111 |
`define ALU_OR 4'b1000 |
`define ALU_XOR 4'b1001 |
|
//----------------------------------------------------------------- |
// ALU Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_ALU 8'h38 |
`define INST_OR32_ADD 8'h00 |
`define INST_OR32_ADDC 8'h01 |
`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 |
`define INST_OR32_MUL 8'hc6 |
`define INST_OR32_MULU 8'hcb |
|
//----------------------------------------------------------------- |
// 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'h39 |
`define INST_OR32_SFXXI 8'h2F |
`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_CUST1 8'h1C |
|
`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 |
|
`define SPR_REG_MACLO 16'h0080 |
`define SPR_REG_MACHI 16'h0081 |
|
//----------------------------------------------------------------- |
// 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 |
`define OR32_SR_ICACHE_FLUSH 17 |
`define OR32_SR_DCACHE_FLUSH 18 |
|
//----------------------------------------------------------------- |
// 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_TRAP 32'h00000600 |
`define VECTOR_NMI 32'h00000700 |
`define VECTOR_BUS_ERROR 32'h00000800 |