OpenCores
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

powered by: WebSVN 2.1.0

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