URL
https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk
Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc
Compare Revisions
- This comparison shows the changes necessary to convert path
/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk/mpsoc/src_processor
- from Rev 21 to Rev 25
- ↔ Reverse comparison
Rev 21 → Rev 25
/aeMB/sw/Makefile
1,4 → 1,4
all: |
cd compile; ./gccrom ../main.c; |
cd compile; cp ram.mif ../ram00.mif; |
cd compile; sh gccrom ../main.c; |
cd compile; cp ram.mif ../ram${CORE_ID}.mif; cp ram.bin ../ram${CORE_ID}.bin; |
|
/aeMB/sw/compile/gccrom
5,10 → 5,11
|
|
# Compile using C pre-processor |
|
ELFFILE="rom" |
XILFLAGS="-mtune=v5.00 -mxl-soft-div -msoft-float -mxl-barrel-shift -mno-xl-soft-mul" |
CXXFLAGS="-O1" |
LNKFLAGS="-Wl,-defsym -Wl,_STACK_SIZE=0x400 -Wl,-defsym -Wl,_HEAP_SIZE=0x400" |
LNKFLAGS="-Wl,-defsym -Wl,_STACK_SIZE=${STACK_SIZE} -Wl,-defsym -Wl,_HEAP_SIZE=${HEAP_SIZE}" |
LIBFLAGS="" |
INCFLAGS="-Icc/" |
RAMSIZE="3FFF" #for aeMB ramwith of 12 |
33,9 → 34,11
$TOOLCHAIN/aemb/bin/mb-objcopy -O ihex $ELFFILE $ELFFILE.ihex && \ |
#echo "copy2ihex=$?" && \ |
|
# Generate a MIF file from the IHEX file |
$TOOLCHAIN/ihex2mif/ihex2mif -f $ELFFILE.ihex -e $RAMSIZE -o ram.mif && \ |
# Generate a MIF & BIN files from the IHEX file |
$TOOLCHAIN/bin/ihex2mif -f $ELFFILE.ihex -e $RAMSIZE -o ram.mif && \ |
echo "ihex2mif=$?" |
$TOOLCHAIN/bin/ihex2bin -i $ELFFILE.ihex -o ram.bin && \ |
echo "ihex2bin=$?" |
|
# echo the checksum |
#MD5=$(sha1sum $ELFFILE | cut -c1-32) && \ |
/altor32/rtl/cpu/altor.v
0,0 → 1,112
module altor #( |
parameter BOOT_VECTOR=32'h00000000, |
parameter ISR_VECTOR =32'h00000000, |
parameter ENABLE_ICACHE="ENABLED", |
parameter ENABLE_DCACHE="ENABLED", |
parameter REGISTER_FILE_TYPE="ALTERA", |
parameter SUPPORT_32REGS="ENABLED", |
parameter PIPELINED_FETCH="ENABLED" |
|
) |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
input en_i /*verilator public*/, |
|
|
input intr_i /*verilator public*/, |
input nmi_i /*verilator public*/, |
output fault_o /*verilator public*/, |
output break_o /*verilator public*/, |
|
// Instruction memory |
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*/, |
|
// Data memory |
output [31:0] dmem_addr_o /*verilator public*/, |
output [31:0] dmem_dat_o /*verilator public*/, |
input [31:0] dmem_dat_i /*verilator public*/, |
output [3:0] dmem_sel_o /*verilator public*/, |
output [2:0] dmem_cti_o /*verilator public*/, |
output dmem_cyc_o /*verilator public*/, |
output dmem_we_o /*verilator public*/, |
output dmem_stb_o /*verilator public*/, |
// input dmem_stall_i/*verilator public*/, |
input dmem_ack_i/*verilator public*/ |
); |
|
|
wire [31:0] i_addr_o,d_addr_o; |
wire imem_stall_i,dmem_stall_i; |
cpu |
#( |
.BOOT_VECTOR(BOOT_VECTOR), |
.ISR_VECTOR(ISR_VECTOR), |
.REGISTER_FILE_TYPE(REGISTER_FILE_TYPE), |
.ENABLE_ICACHE(ENABLE_ICACHE), |
.ENABLE_DCACHE(ENABLE_DCACHE), |
.SUPPORT_32REGS(SUPPORT_32REGS), |
.PIPELINED_FETCH(SUPPORT_32REGS) |
) |
u1_cpu |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
.intr_i(intr_i), |
.nmi_i(nmi_i), |
|
// Status |
.fault_o(fault_o), |
.break_o(break_o), |
|
// Instruction memory |
.imem_addr_o(i_addr_o), |
.imem_dat_i(imem_dat_i), |
.imem_cti_o(imem_cti_o), |
.imem_cyc_o(imem_cyc_o), |
.imem_stb_o(imem_stb_o), |
.imem_stall_i(imem_stall_i), |
.imem_ack_i(imem_ack_i), |
|
// Data memory |
.dmem_addr_o(d_addr_o), |
.dmem_dat_o(dmem_dat_o), |
.dmem_dat_i(dmem_dat_i), |
.dmem_sel_o(dmem_sel_o), |
.dmem_cti_o(dmem_cti_o), |
.dmem_cyc_o(dmem_cyc_o), |
.dmem_we_o(dmem_we_o), |
.dmem_stb_o(dmem_stb_o), |
.dmem_stall_i(dmem_stall_i), |
.dmem_ack_i(dmem_ack_i) |
); |
|
assign imem_addr_o= {2'b00,i_addr_o[31:2]}; |
assign dmem_addr_o= {2'b00,d_addr_o[31:2]}; |
|
reg imem_stb_o_delay,dmem_stb_o_delay; |
/* |
always @(posedge clk_i) begin |
if(rst_i) begin |
imem_stb_o_delay<=1'b0; |
dmem_stb_o_delay<=1'b0; |
end else begin |
imem_stb_o_delay<=imem_stb_o; |
dmem_stb_o_delay<=dmem_stb_o; |
end |
end |
*/ |
|
wire stall_i=~en_i; |
assign imem_stall_i = (imem_stb_o & ~imem_ack_i)|stall_i ; |
assign dmem_stall_i = (dmem_stb_o & ~dmem_ack_i)|stall_i ; |
|
endmodule |
altor32/rtl/cpu/altor.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32.v
===================================================================
--- altor32/rtl/cpu/altor32.v (nonexistent)
+++ altor32/rtl/cpu/altor32.v (revision 25)
@@ -0,0 +1,503 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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 - AltOR32 CPU (Pipelined Wishbone Interfaces)
+//-----------------------------------------------------------------
+module cpu
+(
+ // General
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ input intr_i /*verilator public*/,
+ input nmi_i /*verilator public*/,
+ output fault_o /*verilator public*/,
+ output break_o /*verilator public*/,
+
+ // Instruction memory
+ 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*/,
+
+ // Data memory
+ output [31:0] dmem_addr_o /*verilator public*/,
+ output [31:0] dmem_dat_o /*verilator public*/,
+ input [31:0] dmem_dat_i /*verilator public*/,
+ output [3:0] dmem_sel_o /*verilator public*/,
+ output [2:0] dmem_cti_o /*verilator public*/,
+ output dmem_cyc_o /*verilator public*/,
+ output dmem_we_o /*verilator public*/,
+ output dmem_stb_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 = "ENABLED";
+parameter ENABLE_DCACHE = "DISABLED";
+parameter SUPPORT_32REGS = "ENABLED";
+parameter PIPELINED_FETCH = "ENABLED";
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+// Instruction fetch
+wire fetch_rd_w;
+wire [31:0] fetch_pc_w;
+wire [31:0] fetch_opcode_w;
+wire fetch_valid_w;
+
+// Decode opcode / PC / state
+wire [31:0] dec_opcode_w;
+wire [31:0] dec_opcode_pc_w;
+wire dec_opcode_valid_w;
+
+// Register number (rA)
+wire [4:0] dec_ra_w;
+
+// Register number (rB)
+wire [4:0] dec_rb_w;
+
+// Destination register number (pre execute stage)
+wire [4:0] dec_rd_w;
+
+// Register value (rA)
+wire [31:0] dec_ra_val_w;
+
+// Register value (rB)
+wire [31:0] dec_rb_val_w;
+
+// Destination register number (post execute stage)
+wire [4:0] ex_rd_w;
+
+// Current executing instruction
+wire [31:0] ex_opcode_w;
+
+// Result from execute
+wire [31:0] ex_result_w;
+wire [63:0] ex_mult_res_w;
+
+// Branch request
+wire ex_branch_w;
+wire [31:0] ex_branch_pc_w;
+wire ex_stall_w;
+
+// Register writeback value
+wire [4:0] wb_rd_w;
+wire [31:0] wb_rd_val_w;
+
+// Register writeback enable
+wire wb_rd_write_w;
+
+wire [31:0] dcache_addr_w;
+wire [31:0] dcache_data_out_w;
+wire [31:0] dcache_data_in_w;
+wire [3:0] dcache_sel_w;
+wire dcache_we_w;
+wire dcache_stb_w;
+wire dcache_cyc_w;
+wire dcache_ack_w;
+wire dcache_stall_w;
+
+wire icache_flush_w;
+wire dcache_flush_w;
+
+//-----------------------------------------------------------------
+// Instruction Cache
+//-----------------------------------------------------------------
+generate
+if (ENABLE_ICACHE == "ENABLED")
+begin : ICACHE
+ // Instruction cache
+ altor32_icache
+ #(
+ .BOOT_VECTOR(BOOT_VECTOR)
+ )
+ u_icache
+ (
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ // Processor interface
+ .rd_i(fetch_rd_w),
+ .pc_i(fetch_pc_w),
+ .instruction_o(fetch_opcode_w),
+ .valid_o(fetch_valid_w),
+ .invalidate_i(icache_flush_w),
+
+ // Instruction memory
+ .wbm_addr_o(imem_addr_o),
+ .wbm_dat_i(imem_dat_i),
+ .wbm_cti_o(imem_cti_o),
+ .wbm_cyc_o(imem_cyc_o),
+ .wbm_stb_o(imem_stb_o),
+ .wbm_stall_i(imem_stall_i),
+ .wbm_ack_i(imem_ack_i)
+ );
+end
+//-----------------------------------------------------------------
+// No instruction cache
+//-----------------------------------------------------------------
+else
+begin : NO_ICACHE
+ altor32_noicache
+ u_icache
+ (
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ // Processor interface
+ .rd_i(fetch_rd_w),
+ .pc_i(fetch_pc_w),
+ .instruction_o(fetch_opcode_w),
+ .valid_o(fetch_valid_w),
+ .invalidate_i(icache_flush_w),
+
+ // Instruction memory
+ .wbm_addr_o(imem_addr_o),
+ .wbm_dat_i(imem_dat_i),
+ .wbm_cti_o(imem_cti_o),
+ .wbm_cyc_o(imem_cyc_o),
+ .wbm_stb_o(imem_stb_o),
+ .wbm_stall_i(imem_stall_i),
+ .wbm_ack_i(imem_ack_i)
+ );
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Instruction Fetch
+//-----------------------------------------------------------------
+altor32_fetch
+#(
+ .BOOT_VECTOR(BOOT_VECTOR),
+ .PIPELINED_FETCH(PIPELINED_FETCH)
+)
+u_fetch
+(
+ // General
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ // Instruction memory
+ .pc_o(fetch_pc_w),
+ .data_i(fetch_opcode_w),
+ .fetch_o(fetch_rd_w),
+ .data_valid_i(fetch_valid_w),
+
+ // Fetched opcode
+ .opcode_o(dec_opcode_w),
+ .opcode_pc_o(dec_opcode_pc_w),
+ .opcode_valid_o(dec_opcode_valid_w),
+
+ // Branch target
+ .branch_i(ex_branch_w),
+ .branch_pc_i(ex_branch_pc_w),
+ .stall_i(ex_stall_w),
+
+ // Decoded register details
+ .ra_o(dec_ra_w),
+ .rb_o(dec_rb_w),
+ .rd_o(dec_rd_w)
+);
+
+//-----------------------------------------------------------------
+// [Xilinx] Register file
+//-----------------------------------------------------------------
+generate
+if (REGISTER_FILE_TYPE == "XILINX")
+begin : REGFILE_XIL
+ altor32_regfile_xil
+ #(
+ .SUPPORT_32REGS(SUPPORT_32REGS)
+ )
+ u_regfile
+ (
+ // Clocking
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+ .wr_i(wb_rd_write_w),
+
+ // Tri-port
+ .ra_i(dec_ra_w),
+ .rb_i(dec_rb_w),
+ .rd_i(wb_rd_w),
+ .reg_ra_o(dec_ra_val_w),
+ .reg_rb_o(dec_rb_val_w),
+ .reg_rd_i(wb_rd_val_w)
+ );
+end
+//-----------------------------------------------------------------
+// [Altera] Register file
+//-----------------------------------------------------------------
+else if (REGISTER_FILE_TYPE == "ALTERA")
+begin : REGFILE_ALT
+ altor32_regfile_alt
+ #(
+ .SUPPORT_32REGS(SUPPORT_32REGS)
+ )
+ u_regfile
+ (
+ // Clocking
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+ .wr_i(wb_rd_write_w),
+
+ // Tri-port
+ .ra_i(dec_ra_w),
+ .rb_i(dec_rb_w),
+ .rd_i(wb_rd_w),
+ .reg_ra_o(dec_ra_val_w),
+ .reg_rb_o(dec_rb_val_w),
+ .reg_rd_i(wb_rd_val_w)
+ );
+end
+//-----------------------------------------------------------------
+// [Simulation] Register file
+//-----------------------------------------------------------------
+else
+begin : REGFILE_SIM
+ altor32_regfile_sim
+ #(
+ .SUPPORT_32REGS(SUPPORT_32REGS)
+ )
+ u_regfile
+ (
+ // Clocking
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+ .wr_i(wb_rd_write_w),
+
+ // Tri-port
+ .ra_i(dec_ra_w),
+ .rb_i(dec_rb_w),
+ .rd_i(wb_rd_w),
+ .reg_ra_o(dec_ra_val_w),
+ .reg_rb_o(dec_rb_val_w),
+ .reg_rd_i(wb_rd_val_w)
+ );
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Data cache
+//-----------------------------------------------------------------
+generate
+if (ENABLE_DCACHE == "ENABLED")
+begin : DCACHE
+ altor32_dcache
+ u_dcache
+ (
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ .flush_i(dcache_flush_w),
+
+ // Processor interface
+ .address_i({dcache_addr_w[31:2], 2'b00}),
+ .data_o(dcache_data_in_w),
+ .data_i(dcache_data_out_w),
+ .we_i(dcache_we_w),
+ .stb_i(dcache_stb_w),
+ .sel_i(dcache_sel_w),
+ .stall_o(dcache_stall_w),
+ .ack_o(dcache_ack_w),
+
+ // Memory interface (slave)
+ .mem_addr_o(dmem_addr_o),
+ .mem_data_i(dmem_dat_i),
+ .mem_data_o(dmem_dat_o),
+ .mem_sel_o(dmem_sel_o),
+ .mem_we_o(dmem_we_o),
+ .mem_stb_o(dmem_stb_o),
+ .mem_cyc_o(dmem_cyc_o),
+ .mem_cti_o(dmem_cti_o),
+ .mem_stall_i(dmem_stall_i),
+ .mem_ack_i(dmem_ack_i)
+ );
+end
+//-----------------------------------------------------------------
+// No data cache
+//-----------------------------------------------------------------
+else
+begin: NO_DCACHE
+ assign dmem_addr_o = {dcache_addr_w[31:2], 2'b00};
+ assign dmem_dat_o = dcache_data_out_w;
+ assign dcache_data_in_w = dmem_dat_i;
+ assign dmem_sel_o = dcache_sel_w;
+ assign dmem_cyc_o = dcache_cyc_w;
+ assign dmem_we_o = dcache_we_w;
+ assign dmem_stb_o = dcache_stb_w;
+ assign dmem_cti_o = 3'b111;
+ assign dcache_ack_w = dmem_ack_i;
+ assign dcache_stall_w = dmem_stall_i;
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Execution unit
+//-----------------------------------------------------------------
+altor32_exec
+#(
+ .BOOT_VECTOR(BOOT_VECTOR),
+ .ISR_VECTOR(ISR_VECTOR)
+)
+u_exec
+(
+ // General
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ .intr_i(intr_i),
+ .break_i(nmi_i),
+
+ // Status
+ .fault_o(fault_o),
+ .break_o(break_o),
+
+ // Cache control
+ .icache_flush_o(icache_flush_w),
+ .dcache_flush_o(dcache_flush_w),
+
+ // Branch target
+ .branch_o(ex_branch_w),
+ .branch_pc_o(ex_branch_pc_w),
+ .stall_o(ex_stall_w),
+
+ // Opcode & arguments
+ .opcode_i(dec_opcode_w),
+ .opcode_pc_i(dec_opcode_pc_w),
+ .opcode_valid_i(dec_opcode_valid_w),
+
+ // Operands
+ .reg_ra_i(dec_ra_w),
+ .reg_ra_value_i(dec_ra_val_w),
+ .reg_rb_i(dec_rb_w),
+ .reg_rb_value_i(dec_rb_val_w),
+ .reg_rd_i(dec_rd_w),
+
+ // Output
+ .opcode_o(ex_opcode_w),
+ .opcode_pc_o(/* not used */),
+ .reg_rd_o(ex_rd_w),
+ .reg_rd_value_o(ex_result_w),
+ .mult_res_o(ex_mult_res_w),
+
+ // Register write back bypass
+ .wb_rd_i(wb_rd_w),
+ .wb_rd_value_i(wb_rd_val_w),
+
+ // Memory Interface
+ .dmem_addr_o(dcache_addr_w),
+ .dmem_data_out_o(dcache_data_out_w),
+ .dmem_data_in_i(dcache_data_in_w),
+ .dmem_sel_o(dcache_sel_w),
+ .dmem_we_o(dcache_we_w),
+ .dmem_stb_o(dcache_stb_w),
+ .dmem_cyc_o(dcache_cyc_w),
+ .dmem_stall_i(dcache_stall_w),
+ .dmem_ack_i(dcache_ack_w)
+);
+
+//-----------------------------------------------------------------
+// Register file writeback
+//-----------------------------------------------------------------
+altor32_writeback
+u_wb
+(
+ // General
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ // Opcode
+ .opcode_i(ex_opcode_w),
+
+ // Register target
+ .rd_i(ex_rd_w),
+
+ // ALU result
+ .alu_result_i(ex_result_w),
+
+ // Memory load result
+ .mem_result_i(dcache_data_in_w),
+ .mem_offset_i(dcache_addr_w[1:0]),
+ .mem_ready_i(dcache_ack_w),
+
+ // Multiplier result
+ .mult_result_i(ex_mult_res_w),
+
+ // Outputs
+ .write_enable_o(wb_rd_write_w),
+ .write_addr_o(wb_rd_w),
+ .write_data_o(wb_rd_val_w)
+);
+
+//-------------------------------------------------------------------
+// Hooks for debug
+//-------------------------------------------------------------------
+`ifdef verilator
+ function [31:0] get_pc;
+ // verilator public
+ get_pc = dec_opcode_pc_w;
+ endfunction
+ function get_fault;
+ // verilator public
+ get_fault = fault_o;
+ endfunction
+ function get_break;
+ // verilator public
+ get_break = break_o;
+ endfunction
+`endif
+
+endmodule
altor32/rtl/cpu/altor32.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_alu.v
===================================================================
--- altor32/rtl/cpu/altor32_alu.v (nonexistent)
+++ altor32/rtl/cpu/altor32_alu.v (revision 25)
@@ -0,0 +1,256 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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 - 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*/,
+
+ // Comparison
+ output reg equal_o /*verilator public*/,
+ output reg greater_than_signed_o /*verilator public*/,
+ output reg greater_than_o /*verilator public*/,
+ output reg less_than_signed_o /*verilator public*/,
+ output reg less_than_o /*verilator public*/,
+ output flag_update_o /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+`define ADD_FUNCTION
+`include "altor32_funcs.v"
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+reg [31:0] result_r;
+
+reg [31:16] shift_right_fill_r;
+reg [31:0] shift_right_1_r;
+reg [31:0] shift_right_2_r;
+reg [31:0] shift_right_4_r;
+reg [31:0] shift_right_8_r;
+
+reg [31:0] shift_left_1_r;
+reg [31:0] shift_left_2_r;
+reg [31:0] shift_left_4_r;
+reg [31:0] shift_left_8_r;
+
+//-----------------------------------------------------------------
+// ALU
+//-----------------------------------------------------------------
+always @ (op_i or a_i or b_i or c_i)
+begin
+ shift_right_fill_r={16{1'bx}};
+ shift_right_1_r={32{1'bx}};
+ shift_right_2_r={32{1'bx}};
+ shift_right_4_r={32{1'bx}};
+ shift_right_8_r={32{1'bx}};
+ shift_left_1_r={32{1'bx}};
+ shift_left_2_r={32{1'bx}};
+ shift_left_4_r={32{1'bx}};
+ shift_left_8_r={32{1'bx}};
+ case (op_i)
+
+ //----------------------------------------------
+ // Shift Left
+ //----------------------------------------------
+ `ALU_SHIFTL :
+ begin
+ if (b_i[0] == 1'b1)
+ shift_left_1_r = {a_i[30:0],1'b0};
+ else
+ shift_left_1_r = a_i;
+
+ if (b_i[1] == 1'b1)
+ shift_left_2_r = {shift_left_1_r[29:0],2'b00};
+ else
+ shift_left_2_r = shift_left_1_r;
+
+ if (b_i[2] == 1'b1)
+ shift_left_4_r = {shift_left_2_r[27:0],4'b0000};
+ else
+ shift_left_4_r = shift_left_2_r;
+
+ if (b_i[3] == 1'b1)
+ shift_left_8_r = {shift_left_4_r[23:0],8'b00000000};
+ else
+ shift_left_8_r = shift_left_4_r;
+
+ if (b_i[4] == 1'b1)
+ result_r = {shift_left_8_r[15:0],16'b0000000000000000};
+ else
+ result_r = shift_left_8_r;
+
+ 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_r = 16'b1111111111111111;
+ else
+ shift_right_fill_r = 16'b0000000000000000;
+
+ if (b_i[0] == 1'b1)
+ shift_right_1_r = {shift_right_fill_r[31], a_i[31:1]};
+ else
+ shift_right_1_r = a_i;
+
+ if (b_i[1] == 1'b1)
+ shift_right_2_r = {shift_right_fill_r[31:30], shift_right_1_r[31:2]};
+ else
+ shift_right_2_r = shift_right_1_r;
+
+ if (b_i[2] == 1'b1)
+ shift_right_4_r = {shift_right_fill_r[31:28], shift_right_2_r[31:4]};
+ else
+ shift_right_4_r = shift_right_2_r;
+
+ if (b_i[3] == 1'b1)
+ shift_right_8_r = {shift_right_fill_r[31:24], shift_right_4_r[31:8]};
+ else
+ shift_right_8_r = shift_right_4_r;
+
+ if (b_i[4] == 1'b1)
+ result_r = {shift_right_fill_r[31:16], shift_right_8_r[31:16]};
+ else
+ result_r = shift_right_8_r;
+
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ //----------------------------------------------
+ // Arithmetic
+ //----------------------------------------------
+ `ALU_ADD :
+ begin
+ {c_o, result_r} = (a_i + b_i);
+ c_update_o = 1'b1;
+ end
+ `ALU_ADDC :
+ begin
+ {c_o, result_r} = (a_i + b_i) + {31'h00000000, c_i};
+ c_update_o = 1'b1;
+ end
+ `ALU_SUB :
+ begin
+ result_r = (a_i - b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ //----------------------------------------------
+ // Logical
+ //----------------------------------------------
+ `ALU_AND :
+ begin
+ result_r = (a_i & b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ `ALU_OR :
+ begin
+ result_r = (a_i | b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ `ALU_XOR :
+ begin
+ result_r = (a_i ^ b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ default :
+ begin
+ result_r = a_i;
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ endcase
+end
+
+assign p_o = result_r;
+
+//-----------------------------------------------------------------
+// Comparisons
+//-----------------------------------------------------------------
+always @ *
+begin
+ if (a_i == b_i)
+ equal_o = 1'b1;
+ else
+ equal_o = 1'b0;
+
+ if (a_i < b_i)
+ less_than_o = 1'b1;
+ else
+ less_than_o = 1'b0;
+
+ if (a_i > b_i)
+ greater_than_o = 1'b1;
+ else
+ greater_than_o = 1'b0;
+
+ less_than_signed_o = less_than_signed(a_i, b_i);
+ greater_than_signed_o = ~(less_than_signed_o | equal_o);
+end
+
+assign flag_update_o = (op_i == `ALU_COMPARE);
+
+endmodule
altor32/rtl/cpu/altor32_alu.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_dcache.v
===================================================================
--- altor32/rtl/cpu/altor32_dcache.v (nonexistent)
+++ altor32/rtl/cpu/altor32_dcache.v (revision 25)
@@ -0,0 +1,1035 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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 - Data Cache (write back)
+//-----------------------------------------------------------------
+module altor32_dcache
+(
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ input flush_i /*verilator public*/,
+
+ // Input (CPU)
+ input [31:0] address_i /*verilator public*/,
+ output [31:0] data_o /*verilator public*/,
+ input [31:0] data_i /*verilator public*/,
+ input we_i /*verilator public*/,
+ input stb_i /*verilator public*/,
+ input [3:0] sel_i /*verilator public*/,
+ output stall_o /*verilator public*/,
+ output ack_o /*verilator public*/,
+
+ // Output (Memory)
+ output [31:0] mem_addr_o /*verilator public*/,
+ input [31:0] mem_data_i /*verilator public*/,
+ output [31:0] mem_data_o /*verilator public*/,
+ output [2:0] mem_cti_o /*verilator public*/,
+ output mem_cyc_o /*verilator public*/,
+ output mem_stb_o /*verilator public*/,
+ output mem_we_o /*verilator public*/,
+ output [3:0] mem_sel_o /*verilator public*/,
+ input mem_stall_i/*verilator public*/,
+ input mem_ack_i/*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
+parameter CACHE_LINE_SIZE_BYTES = 2 ** CACHE_LINE_SIZE_WIDTH; /* 32 bytes / 8 words per line */
+parameter CACHE_LINE_ADDR_WIDTH = 8; /* 256 lines */
+parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit = 8 words */
+parameter CACHE_TAG_ENTRIES = 2 ** CACHE_LINE_ADDR_WIDTH ; /* 256 tag entries */
+parameter CACHE_DSIZE = CACHE_LINE_ADDR_WIDTH * CACHE_LINE_SIZE_BYTES; /* 8KB data */
+parameter CACHE_DWIDTH = CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 2; /* 11-bits */
+
+parameter CACHE_TAG_WIDTH = 16; /* 16-bit tag entry size */
+parameter CACHE_TAG_LINE_ADDR_WIDTH = CACHE_TAG_WIDTH - 2; /* 14 bits of data (tag entry size minus valid/dirty bit) */
+
+parameter CACHE_TAG_ADDR_LOW = CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH;
+parameter CACHE_TAG_ADDR_HIGH = CACHE_TAG_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH - 1;
+
+// Tag fields
+parameter CACHE_TAG_DIRTY_BIT = 14;
+parameter CACHE_TAG_VALID_BIT = 15;
+parameter ADDR_NO_CACHE_BIT = 25;
+parameter ADDR_CACHE_BYPASS_BIT = 31;
+
+parameter FLUSH_INITIAL = 0;
+
+// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+// |--------------| | | | | | | | | | | | | | | | |
+// +--------------------+ +-------------------+ +-----------+
+// Tag entry Line address Address
+// (15-bits) (8-bits) within line
+// (5-bits)
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry;
+wire [CACHE_TAG_WIDTH-1:0] tag_data_out;
+reg [CACHE_TAG_WIDTH-1:0] tag_data_in;
+reg tag_wr;
+
+wire [CACHE_DWIDTH-1:0] cache_address;
+wire [31:0] cache_data_r;
+reg [31:0] cache_data_w;
+reg [3:0] cache_wr;
+
+wire [31:2] cache_update_addr;
+wire [31:0] cache_update_data_w;
+wire [31:0] cache_update_data_r;
+wire cache_update_wr;
+
+reg ack;
+
+reg fill;
+reg evict;
+wire done;
+
+wire [31:0] data_r;
+reg rd_single;
+reg [3:0] wr_single;
+
+reg req_rd;
+reg [3:0] req_wr;
+reg req_ack;
+reg [31:0] req_address;
+reg [31:0] req_data;
+
+reg req_flush;
+reg req_init;
+reg flush_single;
+
+wire [31:0] line_address;
+
+// Current state
+parameter STATE_IDLE = 0;
+parameter STATE_SINGLE = 1;
+parameter STATE_CHECK = 2;
+parameter STATE_FETCH = 3;
+parameter STATE_WAIT = 4;
+parameter STATE_WAIT2 = 5;
+parameter STATE_WRITE = 6;
+parameter STATE_SINGLE_READY= 7;
+parameter STATE_EVICTING = 8;
+parameter STATE_UPDATE = 9;
+parameter STATE_FLUSH1 = 10;
+parameter STATE_FLUSH2 = 11;
+parameter STATE_FLUSH3 = 12;
+parameter STATE_FLUSH4 = 13;
+reg [3:0] state;
+
+wire [31:0] muxed_address = (state == STATE_IDLE) ? address_i : req_address;
+
+assign tag_entry = muxed_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
+assign cache_address = {tag_entry, muxed_address[CACHE_LINE_SIZE_WIDTH-1:2]};
+
+assign data_o = (state == STATE_SINGLE_READY) ? data_r : cache_data_r;
+assign stall_o = (state != STATE_IDLE) | req_flush | flush_i;
+
+wire valid = tag_data_out[CACHE_TAG_VALID_BIT];
+wire dirty = tag_data_out[CACHE_TAG_DIRTY_BIT];
+
+// Access is cacheable?
+wire cacheable = ~muxed_address[ADDR_NO_CACHE_BIT] & ~muxed_address[ADDR_CACHE_BYPASS_BIT];
+
+// Address matches cache tag
+wire addr_hit = (req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]);
+
+// Cache hit?
+wire hit = cacheable & valid & addr_hit & (state == STATE_CHECK);
+
+assign ack_o = ack | hit;
+
+assign line_address[31:CACHE_TAG_ADDR_HIGH+1] = {(31-CACHE_TAG_ADDR_HIGH){1'b0}};
+assign line_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] = tag_entry;
+assign line_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] = tag_data_out[13:0];
+assign line_address[CACHE_LINE_SIZE_WIDTH-1:0] = {CACHE_LINE_SIZE_WIDTH{1'b0}};
+
+// Only allow cache write when same line present in the write state
+wire cache_wr_enable = (state == STATE_WRITE) ? valid & addr_hit : 1'b1;
+
+//-----------------------------------------------------------------
+// Next State Logic
+//-----------------------------------------------------------------
+reg [3:0] next_state_r;
+always @ *
+begin
+ next_state_r = state;
+
+ case (state)
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Cache flush request
+ if (flush_i | req_flush)
+ next_state_r = STATE_FLUSH2;
+ // Read (uncacheable)
+ else if (stb_i & ~we_i & ~cacheable)
+ next_state_r = STATE_SINGLE;
+ // Read (cacheable)
+ else if (stb_i & ~we_i)
+ next_state_r = STATE_CHECK;
+ // Write (uncacheable)
+ else if (stb_i & we_i & ~cacheable)
+ next_state_r = STATE_SINGLE;
+ // Write (cacheable)
+ else if (stb_i & we_i)
+ next_state_r = STATE_WRITE;
+ end
+ //-----------------------------------------
+ // WRITE
+ //-----------------------------------------
+ STATE_WRITE :
+ begin
+ // Cache hit (line already dirty)
+ if (valid & addr_hit & dirty)
+ next_state_r = STATE_IDLE;
+ // Cache hit, make line dirty
+ else if (valid & addr_hit & ~dirty)
+ next_state_r = STATE_WAIT2;
+ // Cache dirty
+ else if (valid & dirty)
+ next_state_r = STATE_EVICTING;
+ // Cache miss
+ else
+ next_state_r = STATE_UPDATE;
+ end
+ //-----------------------------------------
+ // EVICTING - Evicting cache line
+ //-----------------------------------------
+ STATE_EVICTING:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Evict for read?
+ if (req_rd)
+ next_state_r = STATE_FETCH;
+ // Evict for write
+ else
+ next_state_r = STATE_UPDATE;
+ end
+ end
+ //-----------------------------------------
+ // UPDATE - Update fetched cache line
+ //-----------------------------------------
+ STATE_UPDATE:
+ begin
+ // Data ready from memory?
+ if (done)
+ next_state_r = STATE_WAIT2;
+ end
+ //-----------------------------------------
+ // CHECK - check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache hit
+ if (valid & addr_hit)
+ next_state_r = STATE_IDLE;
+ // Cache dirty
+ else if (valid & dirty)
+ next_state_r = STATE_EVICTING;
+ // Cache miss
+ else
+ next_state_r = STATE_FETCH;
+ end
+ //-----------------------------------------
+ // FETCH_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_SINGLE:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Single WRITE?
+ if (~req_rd)
+ next_state_r = STATE_SINGLE_READY;
+ // Dirty? Write back
+ else if (valid & dirty & addr_hit)
+ next_state_r = STATE_FLUSH4;
+ // Valid line, invalidate
+ else if (valid & addr_hit)
+ next_state_r = STATE_SINGLE_READY;
+ else
+ next_state_r = STATE_SINGLE_READY;
+ end
+ end
+ //-----------------------------------------
+ // FETCH - Fetch row from memory
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Cache line filled?
+ if (done)
+ next_state_r = STATE_WAIT;
+ end
+ //-----------------------------------------
+ // WAIT - Wait cycle
+ //-----------------------------------------
+ STATE_WAIT :
+ begin
+ // Allow extra wait state to handle write & read collision
+ next_state_r = STATE_WAIT2;
+ end
+ //-----------------------------------------
+ // WAIT2 - Wait cycle
+ //-----------------------------------------
+ STATE_WAIT2 :
+ begin
+ next_state_r = STATE_IDLE;
+ end
+ //-----------------------------------------
+ // SINGLE_READY - Uncached access ready
+ //-----------------------------------------
+ STATE_SINGLE_READY :
+ begin
+ // Allow extra wait state to handle write & read collision
+ next_state_r = STATE_IDLE;
+ end
+ //-----------------------------------------
+ // FLUSHx - Flush dirty lines & invalidate
+ //-----------------------------------------
+ STATE_FLUSH1 :
+ begin
+ if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
+ next_state_r = STATE_WAIT;
+ else
+ next_state_r = STATE_FLUSH2;
+ end
+ //-----------------------------------------
+ // FLUSH2 - Wait state
+ //-----------------------------------------
+ STATE_FLUSH2 :
+ begin
+ // Allow a cycle to read line state
+ next_state_r = STATE_FLUSH3;
+ end
+ //-----------------------------------------
+ // FLUSH3 - Check if line dirty & flush
+ //-----------------------------------------
+ STATE_FLUSH3 :
+ begin
+ // Dirty line? Evict line first
+ if (dirty && ~req_init)
+ next_state_r = STATE_FLUSH4;
+ // Not dirty? Just invalidate
+ else
+ begin
+ if (flush_single)
+ next_state_r = STATE_WAIT;
+ else
+ next_state_r = STATE_FLUSH1;
+ end
+ end
+ //-----------------------------------------
+ // FLUSH4 - Wait for line flush to complete
+ //-----------------------------------------
+ STATE_FLUSH4 :
+ begin
+ // Cache line filled?
+ if (done)
+ begin
+ if (flush_single)
+ next_state_r = STATE_SINGLE_READY;
+ else
+ next_state_r = STATE_FLUSH1;
+ end
+ 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
+
+//-----------------------------------------------------------------
+// Tag Write
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ tag_data_in <= 16'b0;
+ tag_wr <= 1'b0;
+ end
+ else
+ begin
+ tag_wr <= 1'b0;
+
+ case (state)
+ //-----------------------------------------
+ // WRITE
+ //-----------------------------------------
+ STATE_WRITE :
+ begin
+ // Cache hit
+ if (valid & addr_hit)
+ begin
+ // Mark line as dirty
+ if (~dirty)
+ begin
+ tag_data_in <= tag_data_out;
+ tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
+ tag_wr <= 1'b1;
+ end
+ end
+ // Cache miss / cache line doesn't require write back
+ else if (~valid | ~dirty)
+ begin
+ // Update tag memory with this line's details
+ tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
+ tag_wr <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // EVICTING - Evicting cache line
+ //-----------------------------------------
+ STATE_EVICTING:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Update tag memory with this new line's details
+ tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
+ tag_wr <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // UPDATE - Update fetched cache line
+ //-----------------------------------------
+ STATE_UPDATE:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Mark line as dirty
+ tag_data_in <= tag_data_out;
+ tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
+ tag_wr <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // CHECK - check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache hit
+ if (valid & addr_hit)
+ begin
+
+ end
+ // Cache miss / cache line doesn't require write back
+ else if (~valid | ~dirty)
+ begin
+ // Update tag memory with this line's details
+ tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
+ tag_wr <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // FETCH_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_SINGLE:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Single WRITE?
+ if (~req_rd)
+ begin
+ // Invalidate cached version
+ if (valid & addr_hit)
+ begin
+ tag_data_in <= tag_data_out;
+ tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
+ tag_wr <= 1'b1;
+ end
+ end
+ // Valid line (not dirty), just invalidate
+ else if (valid & ~dirty & addr_hit)
+ begin
+ tag_data_in <= tag_data_out;
+ tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
+ tag_wr <= 1'b1;
+ end
+ end
+ end
+
+ //-----------------------------------------
+ // FLUSH3 - Check if line dirty & flush
+ //-----------------------------------------
+ STATE_FLUSH3 :
+ begin
+ // Not dirty? Just invalidate
+ if (~dirty | req_init)
+ begin
+ tag_data_in <= 16'b0;
+ tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
+ tag_wr <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // FLUSH4 - Wait for line flush to complete
+ //-----------------------------------------
+ STATE_FLUSH4 :
+ begin
+ // Cache line filled?
+ if (done)
+ begin
+ // Invalidate line
+ tag_data_in <= 16'b0;
+ tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
+ tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
+ tag_wr <= 1'b1;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Register requests
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ req_address <= 32'h00000000;
+ req_data <= 32'h00000000;
+ req_ack <= 1'b0;
+ req_wr <= 4'h0;
+ req_rd <= 1'b0;
+ req_flush <= 1'b1;
+ req_init <= FLUSH_INITIAL;
+ end
+ else
+ begin
+ if (flush_i)
+ req_flush <= 1'b1;
+
+ case (state)
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Cache flush request
+ if (flush_i | req_flush)
+ begin
+ // Set to first line address
+ req_address <= 32'h00000000;
+ req_flush <= 1'b0;
+ req_ack <= 1'b0;
+ end
+ // Read (uncacheable)
+ else if (stb_i & ~we_i & ~cacheable)
+ begin
+ // Start read single from memory
+ req_address <= address_i;
+ req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
+ req_rd <= 1'b1;
+ req_wr <= 4'b0;
+ req_ack <= 1'b1;
+ end
+ // Read (cacheable)
+ else if (stb_i & ~we_i)
+ begin
+ req_address <= address_i;
+ req_rd <= 1'b1;
+ req_wr <= 4'b0;
+ req_ack <= 1'b1;
+ end
+ // Write (uncacheable)
+ else if (stb_i & we_i & ~cacheable)
+ begin
+ // Perform write single
+ req_address <= address_i;
+ req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
+ req_data <= data_i;
+ req_wr <= sel_i;
+ req_rd <= 1'b0;
+ req_ack <= 1'b1;
+ end
+ // Write (cacheable)
+ else if (stb_i & we_i)
+ begin
+ req_address <= address_i;
+ req_data <= data_i;
+ req_wr <= sel_i;
+ req_rd <= 1'b0;
+ req_ack <= 1'b0;
+ end
+ end
+ //-----------------------------------------
+ // FLUSHx - Flush dirty lines & invalidate
+ //-----------------------------------------
+ STATE_FLUSH1 :
+ begin
+ if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
+ begin
+ req_ack <= 1'b0;
+ req_init <= 1'b0;
+ end
+ else
+ begin
+ // Increment flush line address
+ req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <=
+ req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] + 1;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Cache Data Write
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ cache_data_w <= 32'h00000000;
+ cache_wr <= 4'b0;
+ end
+ else
+ begin
+ cache_wr <= 4'b0;
+
+ case (state)
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE:
+ begin
+ // Write (cacheable)
+ if (stb_i & we_i & cacheable & ~(flush_i | req_flush))
+ begin
+ // Early write which is gated on line match
+ cache_data_w <= data_i;
+ cache_wr <= sel_i;
+ end
+ end
+ //-----------------------------------------
+ // UPDATE - Update fetched cache line
+ //-----------------------------------------
+ STATE_UPDATE:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Update line already in cache
+ cache_data_w <= req_data;
+ cache_wr <= req_wr;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Control
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ wr_single <= 4'h0;
+ rd_single <= 1'b0;
+ flush_single <= 1'b0;
+ fill <= 1'b0;
+ evict <= 1'b0;
+ end
+ else
+ begin
+ fill <= 1'b0;
+ evict <= 1'b0;
+ wr_single <= 4'b0;
+ rd_single <= 1'b0;
+
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Cache flush request
+ if (flush_i | req_flush)
+ begin
+ // Set to first line address
+ flush_single<= 1'b0;
+ end
+ // Read (uncacheable)
+ else if (stb_i & ~we_i & ~cacheable)
+ begin
+ // Start read single from memory
+ rd_single <= 1'b1;
+ end
+ // Write (uncacheable)
+ else if (stb_i & we_i & ~cacheable)
+ begin
+ // Perform write single
+ wr_single <= sel_i;
+ end
+ end
+ //-----------------------------------------
+ // WRITE
+ //-----------------------------------------
+ STATE_WRITE :
+ begin
+ // Cache hit
+ if (valid & addr_hit)
+ begin
+
+ end
+ // Cache dirty
+ else if (valid & dirty)
+ begin
+ // Evict cache line
+ evict <= 1'b1;
+ end
+ // Cache miss
+ else
+ begin
+ // Fill cache line
+ fill <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // EVICTING - Evicting cache line
+ //-----------------------------------------
+ STATE_EVICTING:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Fill cache line
+ fill <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // CHECK - check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache hit
+ if (valid & addr_hit)
+ begin
+
+ end
+ // Cache dirty
+ else if (valid & dirty)
+ begin
+ // Evict cache line
+ evict <= 1'b1;
+ end
+ // Cache miss
+ else
+ begin
+ // Fill cache line
+ fill <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // FETCH_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_SINGLE:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Single WRITE?
+ if (~req_rd)
+ begin
+
+ end
+ // Dirty? Write back
+ else if (valid & dirty & addr_hit)
+ begin
+ // Evict cache line
+ evict <= 1'b1;
+ flush_single<= 1'b1;
+ end
+ end
+ end
+ //-----------------------------------------
+ // FLUSH3 - Check if line dirty & flush
+ //-----------------------------------------
+ STATE_FLUSH3 :
+ begin
+ // Dirty line? Evict line first
+ if (dirty)
+ begin
+ // Evict cache line
+ evict <= 1'b1;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// ACK
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ ack <= 1'b0;
+ else
+ begin
+ ack <= 1'b0;
+
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Write (cacheable), early acknowledge
+ if (~(flush_i | req_flush) & stb_i & we_i & cacheable)
+ ack <= 1'b1;
+ end
+ //-----------------------------------------
+ // FETCH_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_SINGLE:
+ begin
+ // Data ready from memory?
+ if (done)
+ begin
+ // Single WRITE?
+ if (~req_rd)
+ ack <= req_ack;
+ // Dirty? Write back
+ else if (valid & dirty & addr_hit)
+ begin
+
+ end
+ // Valid line, invalidate
+ else if (valid & addr_hit)
+ ack <= req_ack;
+ else
+ ack <= req_ack;
+ end
+ end
+ //-----------------------------------------
+ // WAIT2 - Wait cycle
+ //-----------------------------------------
+ STATE_WAIT2 :
+ begin
+ ack <= req_ack;
+ end
+ //-----------------------------------------
+ // FLUSH4 - Wait for line flush to complete
+ //-----------------------------------------
+ STATE_FLUSH4 :
+ begin
+ if (done & flush_single)
+ ack <= req_ack;
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Instantiation
+//-----------------------------------------------------------------
+
+altor32_dcache_mem_if
+#(
+ .CACHE_LINE_SIZE_WIDTH(CACHE_LINE_SIZE_WIDTH),
+ .CACHE_LINE_WORDS_IDX_MAX(CACHE_LINE_WORDS_IDX_MAX)
+)
+u_mem_if
+(
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ // Cache interface
+ .address_i(muxed_address),
+ .data_i(req_data),
+ .data_o(data_r),
+ .fill_i(fill),
+ .evict_i(evict),
+ .evict_addr_i(line_address),
+ .rd_single_i(rd_single),
+ .wr_single_i(wr_single),
+ .done_o(done),
+
+ // Cache memory (fill/evict)
+ .cache_addr_o(cache_update_addr),
+ .cache_data_o(cache_update_data_w),
+ .cache_data_i(cache_update_data_r),
+ .cache_wr_o(cache_update_wr),
+
+ // Memory interface (slave)
+ .mem_addr_o(mem_addr_o),
+ .mem_data_i(mem_data_i),
+ .mem_data_o(mem_data_o),
+ .mem_cti_o(mem_cti_o),
+ .mem_cyc_o(mem_cyc_o),
+ .mem_stb_o(mem_stb_o),
+ .mem_we_o(mem_we_o),
+ .mem_sel_o(mem_sel_o),
+ .mem_stall_i(mem_stall_i),
+ .mem_ack_i(mem_ack_i)
+);
+
+// Tag memory
+altor32_ram_sp
+#(
+ .WIDTH(CACHE_TAG_WIDTH),
+ .SIZE(CACHE_LINE_ADDR_WIDTH)
+)
+u1_tag_mem
+(
+ .clk_i(clk_i),
+ .dat_o(tag_data_out),
+ .dat_i(tag_data_in),
+ .adr_i(tag_entry),
+ .wr_i(tag_wr)
+);
+
+// Data memory
+altor32_ram_dp
+#(
+ .WIDTH(8),
+ .SIZE(CACHE_DWIDTH)
+)
+u2_data_mem0
+(
+ .aclk_i(clk_i),
+ .aadr_i(cache_address),
+ .adat_o(cache_data_r[7:0]),
+ .adat_i(cache_data_w[7:0]),
+ .awr_i(cache_wr[0] & cache_wr_enable),
+
+ .bclk_i(clk_i),
+ .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
+ .bdat_o(cache_update_data_r[7:0]),
+ .bdat_i(cache_update_data_w[7:0]),
+ .bwr_i(cache_update_wr)
+);
+
+altor32_ram_dp
+#(
+ .WIDTH(8),
+ .SIZE(CACHE_DWIDTH)
+)
+u2_data_mem1
+(
+ .aclk_i(clk_i),
+ .aadr_i(cache_address),
+ .adat_o(cache_data_r[15:8]),
+ .adat_i(cache_data_w[15:8]),
+ .awr_i(cache_wr[1] & cache_wr_enable),
+
+ .bclk_i(clk_i),
+ .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
+ .bdat_o(cache_update_data_r[15:8]),
+ .bdat_i(cache_update_data_w[15:8]),
+ .bwr_i(cache_update_wr)
+);
+
+altor32_ram_dp
+#(
+ .WIDTH(8),
+ .SIZE(CACHE_DWIDTH)
+)
+u2_data_mem2
+(
+ .aclk_i(clk_i),
+ .aadr_i(cache_address),
+ .adat_o(cache_data_r[23:16]),
+ .adat_i(cache_data_w[23:16]),
+ .awr_i(cache_wr[2] & cache_wr_enable),
+
+ .bclk_i(clk_i),
+ .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
+ .bdat_o(cache_update_data_r[23:16]),
+ .bdat_i(cache_update_data_w[23:16]),
+ .bwr_i(cache_update_wr)
+);
+
+altor32_ram_dp
+#(
+ .WIDTH(8),
+ .SIZE(CACHE_DWIDTH)
+)
+u2_data_mem3
+(
+ .aclk_i(clk_i),
+ .aadr_i(cache_address),
+ .adat_o(cache_data_r[31:24]),
+ .adat_i(cache_data_w[31:24]),
+ .awr_i(cache_wr[3] & cache_wr_enable),
+
+ .bclk_i(clk_i),
+ .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
+ .bdat_o(cache_update_data_r[31:24]),
+ .bdat_i(cache_update_data_w[31:24]),
+ .bwr_i(cache_update_wr)
+);
+
+endmodule
altor32/rtl/cpu/altor32_dcache.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_dcache_mem_if.v
===================================================================
--- altor32/rtl/cpu/altor32_dcache_mem_if.v (nonexistent)
+++ altor32/rtl/cpu/altor32_dcache_mem_if.v (revision 25)
@@ -0,0 +1,581 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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 - Data Cache Memory Interface
+//-----------------------------------------------------------------
+module altor32_dcache_mem_if
+(
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Cache interface
+ input [31:0] address_i /*verilator public*/,
+ input [31:0] data_i /*verilator public*/,
+ output reg [31:0] data_o /*verilator public*/,
+ input fill_i /*verilator public*/,
+ input evict_i /*verilator public*/,
+ input [31:0] evict_addr_i /*verilator public*/,
+ input rd_single_i /*verilator public*/,
+ input [3:0] wr_single_i /*verilator public*/,
+ output reg done_o /*verilator public*/,
+
+ // Cache memory (fill/evict)
+ output reg [31:2] cache_addr_o /*verilator public*/,
+ output reg [31:0] cache_data_o /*verilator public*/,
+ input [31:0] cache_data_i /*verilator public*/,
+ output reg cache_wr_o /*verilator public*/,
+
+ // Memory interface (slave)
+ output reg [31:0] mem_addr_o /*verilator public*/,
+ input [31:0] mem_data_i /*verilator public*/,
+ output reg [31:0] mem_data_o /*verilator public*/,
+ output reg [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 CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
+parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit -> 8 words */
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+reg [31:CACHE_LINE_SIZE_WIDTH] line_address;
+
+reg [CACHE_LINE_WORDS_IDX_MAX-1:0] response_idx;
+
+reg [CACHE_LINE_WORDS_IDX_MAX-1:0] request_idx;
+wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_request_idx = request_idx + 1'b1;
+
+reg [CACHE_LINE_WORDS_IDX_MAX-1:0] cache_idx;
+wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_cache_idx = cache_idx + 1'b1;
+
+
+// Current state
+parameter STATE_IDLE = 0;
+parameter STATE_FETCH = 1;
+parameter STATE_WRITE_SETUP = 2;
+parameter STATE_WRITE = 3;
+parameter STATE_WRITE_WAIT = 4;
+parameter STATE_MEM_SINGLE = 5;
+parameter STATE_FETCH_WAIT = 6;
+
+reg [3:0] state;
+
+//-----------------------------------------------------------------
+// Next State Logic
+//-----------------------------------------------------------------
+reg [3:0] next_state_r;
+always @ *
+begin
+ next_state_r = state;
+
+ case (state)
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Perform cache evict (write)
+ if (evict_i)
+ next_state_r = STATE_WRITE_SETUP;
+ // Perform cache fill (read)
+ else if (fill_i)
+ next_state_r = STATE_FETCH;
+ // Read/Write single
+ else if (rd_single_i | (|wr_single_i))
+ next_state_r = STATE_MEM_SINGLE;
+ end
+ //-----------------------------------------
+ // FETCH - Fetch line from memory
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Line fetch complete?
+ if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ 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 && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ next_state_r = STATE_IDLE;
+ end
+ //-----------------------------------------
+ // WRITE_SETUP - Wait for data from cache
+ //-----------------------------------------
+ STATE_WRITE_SETUP :
+ next_state_r = STATE_WRITE;
+ //-----------------------------------------
+ // WRITE - Write word to memory
+ //-----------------------------------------
+ STATE_WRITE :
+ begin
+ // Line write complete?
+ if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ next_state_r = STATE_WRITE_WAIT;
+ // Fetch next word for line
+ else if (~mem_stall_i | ~mem_stb_o)
+ next_state_r = STATE_WRITE_SETUP;
+ end
+ //-----------------------------------------
+ // WRITE_WAIT - Wait for write to complete
+ //-----------------------------------------
+ STATE_WRITE_WAIT:
+ begin
+ // Write to memory complete
+ if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ next_state_r = STATE_IDLE;
+ end
+ //-----------------------------------------
+ // MEM_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_MEM_SINGLE:
+ begin
+ // Data ready from memory?
+ if (mem_ack_i)
+ next_state_r = STATE_IDLE;
+ 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
+
+//-----------------------------------------------------------------
+// Control logic
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ line_address <= {32-CACHE_LINE_SIZE_WIDTH{1'b0}};
+ done_o <= 1'b0;
+ data_o <= 32'h00000000;
+ end
+ else
+ begin
+ done_o <= 1'b0;
+
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Perform cache evict (write)
+ if (evict_i)
+ line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH];
+ // Perform cache fill (read)
+ else if (fill_i)
+ line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH];
+ end
+ //-----------------------------------------
+ // FETCH/WRITE_WAIT - Wait for oustanding responses
+ //-----------------------------------------
+ STATE_WRITE_WAIT,
+ STATE_FETCH_WAIT:
+ begin
+ // Write to memory complete
+ if (mem_ack_i)
+ begin
+ // Line write complete?
+ if (response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ done_o <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // MEM_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_MEM_SINGLE:
+ begin
+ // Data ready from memory?
+ if (mem_ack_i)
+ begin
+ data_o <= mem_data_i;
+ done_o <= 1'b1;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Cache Read / Write
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ cache_addr_o <= 30'h00000000;
+ cache_data_o <= 32'h00000000;
+ cache_wr_o <= 1'b0;
+
+ cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
+ end
+ else
+ begin
+ cache_wr_o <= 1'b0;
+
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
+
+ // Perform cache evict (write)
+ if (evict_i)
+ begin
+ // Read data from cache
+ cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_WORDS_IDX_MAX{1'b0}}};
+ end
+ end
+ //-----------------------------------------
+ // FETCH - Fetch line from memory
+ //-----------------------------------------
+ STATE_FETCH,
+ STATE_FETCH_WAIT:
+ begin
+ // Data ready from memory?
+ if (mem_ack_i)
+ begin
+ // Write data into cache
+ cache_addr_o <= {line_address, cache_idx};
+ cache_data_o <= mem_data_i;
+ cache_wr_o <= 1'b1;
+
+ cache_idx <= next_cache_idx;
+ end
+ end
+ //-----------------------------------------
+ // WRITE - Write word to memory
+ //-----------------------------------------
+ STATE_WRITE_SETUP:
+ begin
+
+ end
+ STATE_WRITE,
+ STATE_WRITE_WAIT:
+ begin
+ if (~mem_stall_i | ~mem_stb_o)
+ begin
+ // Setup next word read from cache
+ cache_addr_o <= {line_address, next_cache_idx};
+ cache_idx <= next_cache_idx;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Request
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ mem_addr_o <= 32'h00000000;
+ mem_data_o <= 32'h00000000;
+ mem_sel_o <= 4'h0;
+ mem_cti_o <= 3'b0;
+ mem_stb_o <= 1'b0;
+ mem_we_o <= 1'b0;
+ request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
+ end
+ else
+ begin
+ if (~mem_stall_i)
+ begin
+ mem_stb_o <= 1'b0;
+
+ // TMP
+ if (mem_cti_o == 3'b111)
+ begin
+ //mem_addr_o <= 32'h00000000;
+ mem_data_o <= 32'h00000000;
+ mem_sel_o <= 4'h0;
+ mem_cti_o <= 3'b0;
+ mem_stb_o <= 1'b0;
+ mem_we_o <= 1'b0;
+ end
+ end
+
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
+
+ // Perform cache evict (write)
+ if (evict_i)
+ begin
+
+ end
+ // Perform cache fill (read)
+ else if (fill_i)
+ begin
+ // Start fetch from memory
+ mem_addr_o <= {address_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
+ mem_data_o <= 32'h00000000;
+ mem_sel_o <= 4'b1111;
+ mem_cti_o <= 3'b010;
+ mem_stb_o <= 1'b1;
+ mem_we_o <= 1'b0;
+
+ request_idx <= next_request_idx;
+ end
+ // Read single
+ else if (rd_single_i)
+ begin
+ // Start fetch from memory
+ mem_addr_o <= address_i;
+ mem_data_o <= 32'h00000000;
+ mem_sel_o <= 4'b1111;
+ mem_cti_o <= 3'b111;
+ mem_stb_o <= 1'b1;
+ mem_we_o <= 1'b0;
+ end
+ // Write single
+ else if (|wr_single_i)
+ begin
+ // Start fetch from memory
+ mem_addr_o <= address_i;
+ mem_data_o <= data_i;
+ mem_sel_o <= wr_single_i;
+ mem_cti_o <= 3'b111;
+ mem_stb_o <= 1'b1;
+ mem_we_o <= 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // FETCH - Fetch line from memory
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Previous request accepted?
+ if (~mem_stall_i)
+ begin
+ // Fetch next word for line
+ mem_addr_o <= {line_address, request_idx, 2'b00};
+ mem_stb_o <= 1'b1;
+
+ if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ mem_cti_o <= 3'b111;
+
+ request_idx <= next_request_idx;
+ end
+ end
+ //-----------------------------------------
+ // WRITE - Write word to memory
+ //-----------------------------------------
+ STATE_WRITE :
+ begin
+ // Memory interface can request command?
+ if (~mem_stall_i | ~mem_stb_o)
+ begin
+ // Write data into memory from cache
+ mem_addr_o <= {line_address, request_idx, 2'b00};
+ mem_data_o <= cache_data_i;
+ mem_sel_o <= 4'b1111;
+ mem_stb_o <= 1'b1;
+ mem_we_o <= 1'b1;
+
+ if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ mem_cti_o <= 3'b111;
+ else
+ mem_cti_o <= 3'b010;
+
+ request_idx <= next_request_idx;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Memory Response Counter
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
+ else
+ begin
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
+ end
+ //-----------------------------------------
+ // FETCH - Fetch line from memory
+ //-----------------------------------------
+ STATE_FETCH,
+ STATE_FETCH_WAIT :
+ begin
+ // Data ready from memory?
+ if (mem_ack_i)
+ response_idx <= response_idx + 1'b1;
+ end
+ //-----------------------------------------
+ // WRITE_WAIT - Wait for write to complete
+ //-----------------------------------------
+ STATE_WRITE,
+ STATE_WRITE_SETUP,
+ STATE_WRITE_WAIT:
+ begin
+ // Write to memory complete
+ if (mem_ack_i)
+ response_idx <= response_idx + 1'b1;
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// CYC_O
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ mem_cyc_o <= 1'b0;
+ else
+ begin
+ case (state)
+
+ //-----------------------------------------
+ // IDLE
+ //-----------------------------------------
+ STATE_IDLE :
+ begin
+ // Perform cache evict (write)
+ if (evict_i)
+ begin
+
+ end
+ // Perform cache fill (read)
+ else if (fill_i)
+ mem_cyc_o <= 1'b1;
+ // Read single
+ else if (rd_single_i)
+ mem_cyc_o <= 1'b1;
+ // Write single
+ else if (|wr_single_i)
+ mem_cyc_o <= 1'b1;
+ end
+ //-----------------------------------------
+ // FETCH - Fetch line from memory
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Data ready from memory?
+ if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ mem_cyc_o <= 1'b0;
+ end
+ //-----------------------------------------
+ // WRITE - Write word to memory
+ //-----------------------------------------
+ STATE_WRITE :
+ begin
+ // Write data into memory from cache
+ mem_cyc_o <= 1'b1;
+ end
+ //-----------------------------------------
+ // FETCH/WRITE_WAIT - Wait for responses
+ //-----------------------------------------
+ STATE_WRITE_WAIT,
+ STATE_FETCH_WAIT:
+ begin
+ // Write to memory complete
+ if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
+ mem_cyc_o <= 1'b0;
+ end
+ //-----------------------------------------
+ // MEM_SINGLE - Single access to memory
+ //-----------------------------------------
+ STATE_MEM_SINGLE:
+ begin
+ // Data ready from memory?
+ if (mem_ack_i)
+ mem_cyc_o <= 1'b0;
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+endmodule
altor32/rtl/cpu/altor32_dcache_mem_if.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_defs.v
===================================================================
--- altor32/rtl/cpu/altor32_defs.v (nonexistent)
+++ altor32/rtl/cpu/altor32_defs.v (revision 25)
@@ -0,0 +1,186 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`ifdef ADD_DEF
+`undef ADD_DEF
+
+
+
+`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
+`define ALU_COMPARE 4'b1010
+
+//-----------------------------------------------------------------
+// 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_SFMASK 16'hFD3F
+`define INST_OR32_SFEQ 16'h0520
+`define INST_OR32_SFGES 16'h052B
+`define INST_OR32_SFGEU 16'h0523
+`define INST_OR32_SFGTS 16'h052A
+`define INST_OR32_SFGTU 16'h0522
+`define INST_OR32_SFLES 16'h052D
+`define INST_OR32_SFLEU 16'h0525
+`define INST_OR32_SFLTS 16'h052C
+`define INST_OR32_SFLTU 16'h0524
+`define INST_OR32_SFNE 16'h0521
+
+//-----------------------------------------------------------------
+// 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 SR_SM 0
+`define SR_TEE 1
+`define SR_IEE 2
+`define SR_DCE 3
+`define SR_ICE 4
+`define SR_DME 5
+`define SR_IME 6
+`define SR_LEE 7
+`define SR_CE 8
+`define SR_F 9
+`define SR_CY 10
+`define SR_OV 11
+`define SR_OVE 12
+`define SR_DSX 13
+`define SR_EPH 14
+`define SR_FO 15
+`define SR_SUMRA 16
+`define SR_ICACHE_FLUSH 17
+`define SR_DCACHE_FLUSH 18
+`define SR_STEP 19
+`define SR_DBGEN 20
+
+//-----------------------------------------------------------------
+// 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_BUS_ERROR 32'h00000800
+
+`endif
altor32/rtl/cpu/altor32_defs.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_dfu.v
===================================================================
--- altor32/rtl/cpu/altor32_dfu.v (nonexistent)
+++ altor32/rtl/cpu/altor32_dfu.v (revision 25)
@@ -0,0 +1,200 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module: Data Forwarding Unit
+//-----------------------------------------------------------------
+module altor32_dfu
+(
+ // Input registers
+ input [4:0] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+
+ // Input register contents
+ input [31:0] ra_regval_i /*verilator public*/,
+ input [31:0] rb_regval_i /*verilator public*/,
+
+ // Dest register (EXEC stage)
+ input [4:0] rd_ex_i/*verilator public*/,
+
+ // Dest register (WB stage)
+ input [4:0] rd_wb_i/*verilator public*/,
+
+ // Load pending / target
+ input load_pending_i /*verilator public*/,
+ input [4:0] rd_load_i /*verilator public*/,
+
+ // Multiplier status
+ input mult_ex_i /*verilator public*/,
+
+ // Result (EXEC)
+ input [31:0] result_ex_i /*verilator public*/,
+
+ // Result (WB)
+ input [31:0] result_wb_i /*verilator public*/,
+
+ // Resolved register values
+ output reg [31:0] result_ra_o /*verilator public*/,
+ output reg [31:0] result_rb_o /*verilator public*/,
+
+ // Result required resolving
+ output reg resolved_o /*verilator public*/,
+
+ // Stall due to failed resolve
+ output reg stall_o /*verilator public*/
+);
+
+//-------------------------------------------------------------------
+// Data forwarding unit
+//-------------------------------------------------------------------
+always @ *
+begin
+ // Default to no forwarding
+ result_ra_o = ra_regval_i;
+ result_rb_o = rb_regval_i;
+ stall_o = 1'b0;
+ resolved_o = 1'b0;
+
+ //---------------------------------------------------------------
+ // RA - Hazard detection & forwarding
+ //---------------------------------------------------------------
+
+ // Register[ra] hazard detection & forwarding logic
+ // (higher priority = latest results!)
+ if (ra_i != 5'b00000)
+ begin
+ //---------------------------------------------------------------
+ // RA from load (result not ready)
+ //---------------------------------------------------------------
+ if (ra_i == rd_load_i & load_pending_i)
+ begin
+ stall_o = 1'b1;
+`ifdef CONF_CORE_DEBUG
+ $display(" rA[%d] not ready as load still pending", ra_i);
+`endif
+ end
+ //---------------------------------------------------------------
+ // RA from PC-4 (exec)
+ //---------------------------------------------------------------
+ else if (ra_i == rd_ex_i)
+ begin
+ // Multiplier has one cycle latency, stall if needed now
+ if (mult_ex_i)
+ stall_o = 1'b1;
+ else
+ begin
+ result_ra_o = result_ex_i;
+ resolved_o = 1'b1;
+`ifdef CONF_CORE_DEBUG
+ $display(" rA[%d] forwarded 0x%08x (PC-4)", ra_i, result_ra_o);
+`endif
+ end
+ end
+ //---------------------------------------------------------------
+ // RA from PC-8 (writeback)
+ //---------------------------------------------------------------
+ else if (ra_i == rd_wb_i)
+ begin
+ result_ra_o = result_wb_i;
+
+ resolved_o = 1'b1;
+`ifdef CONF_CORE_DEBUG
+ $display(" rA[%d] forwarded 0x%08x (PC-8)", ra_i, result_ra_o);
+`endif
+ end
+ end
+
+ //---------------------------------------------------------------
+ // RB - Hazard detection & forwarding
+ //---------------------------------------------------------------
+
+ // Register[rb] hazard detection & forwarding logic
+ // (higher priority = latest results!)
+ if (rb_i != 5'b00000)
+ begin
+
+ //---------------------------------------------------------------
+ // RB from load (result not ready)
+ //---------------------------------------------------------------
+ if (rb_i == rd_load_i & load_pending_i)
+ begin
+ stall_o = 1'b1;
+`ifdef CONF_CORE_DEBUG
+ $display(" rB[%d] not ready as load still pending", rb_i);
+`endif
+ end
+ //---------------------------------------------------------------
+ // RB from PC-4 (exec)
+ //---------------------------------------------------------------
+ else if (rb_i == rd_ex_i)
+ begin
+ // Multiplier has one cycle latency, stall if needed now
+ if (mult_ex_i)
+ stall_o = 1'b1;
+ else
+ begin
+ result_rb_o = result_ex_i;
+ resolved_o = 1'b1;
+
+`ifdef CONF_CORE_DEBUG
+ $display(" rB[%d] forwarded 0x%08x (PC-4)", rb_i, result_rb_o);
+`endif
+ end
+ end
+ //---------------------------------------------------------------
+ // RB from PC-8 (writeback)
+ //---------------------------------------------------------------
+ else if (rb_i == rd_wb_i)
+ begin
+ result_rb_o = result_wb_i;
+
+ resolved_o = 1'b1;
+
+`ifdef CONF_CORE_DEBUG
+ $display(" rB[%d] forwarded 0x%08x (PC-8)", rb_i, result_rb_o);
+`endif
+ end
+ end
+end
+
+endmodule
altor32/rtl/cpu/altor32_dfu.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_exec.v
===================================================================
--- altor32/rtl/cpu/altor32_exec.v (nonexistent)
+++ altor32/rtl/cpu/altor32_exec.v (revision 25)
@@ -0,0 +1,1662 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+
+//-----------------------------------------------------------------
+// Module - Instruction Execute
+//-----------------------------------------------------------------
+module altor32_exec
+(
+ // General
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Maskable interrupt
+ input intr_i /*verilator public*/,
+
+ // Break interrupt
+ input break_i /*verilator public*/,
+
+ // Fault
+ output reg fault_o /*verilator public*/,
+
+ // Breakpoint / Trap
+ output reg break_o /*verilator public*/,
+
+ // Cache control
+ output reg icache_flush_o /*verilator public*/,
+ output reg dcache_flush_o /*verilator public*/,
+
+ // Branch
+ output branch_o /*verilator public*/,
+ output [31:0] branch_pc_o /*verilator public*/,
+ output stall_o /*verilator public*/,
+
+ // Opcode & arguments
+ input [31:0] opcode_i /*verilator public*/,
+ input [31:0] opcode_pc_i /*verilator public*/,
+ input opcode_valid_i /*verilator public*/,
+
+ // Reg A
+ input [4:0] reg_ra_i /*verilator public*/,
+ input [31:0] reg_ra_value_i /*verilator public*/,
+
+ // Reg B
+ input [4:0] reg_rb_i /*verilator public*/,
+ input [31:0] reg_rb_value_i /*verilator public*/,
+
+ // Reg D
+ input [4:0] reg_rd_i /*verilator public*/,
+
+ // Output
+ output [31:0] opcode_o /*verilator public*/,
+ output [31:0] opcode_pc_o /*verilator public*/,
+ output [4:0] reg_rd_o /*verilator public*/,
+ output [31:0] reg_rd_value_o /*verilator public*/,
+ output [63:0] mult_res_o /*verilator public*/,
+
+ // Register write back bypass
+ input [4:0] wb_rd_i /*verilator public*/,
+ input [31:0] wb_rd_value_i /*verilator public*/,
+
+ // Memory Interface
+ output reg [31:0] dmem_addr_o /*verilator public*/,
+ output reg [31:0] dmem_data_out_o /*verilator public*/,
+ input [31:0] dmem_data_in_i /*verilator public*/,
+ output reg [3:0] dmem_sel_o /*verilator public*/,
+ output reg dmem_we_o /*verilator public*/,
+ output reg dmem_stb_o /*verilator public*/,
+ output reg dmem_cyc_o /*verilator public*/,
+ input dmem_stall_i /*verilator public*/,
+ input dmem_ack_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+`define ADD_FUNCTION
+`include "altor32_funcs.v"
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter BOOT_VECTOR = 32'h00000000;
+parameter ISR_VECTOR = 32'h00000000;
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+
+// Branch PC
+reg [31:0] pc_branch_q;
+reg pc_fetch_q;
+
+// Exception saved program counter
+reg [31:0] epc_q;
+
+// Supervisor register
+reg [31:0] sr_q;
+
+// Exception saved supervisor register
+reg [31:0] esr_q;
+
+// Destination register number (post execute stage)
+reg [4:0] ex_rd_q;
+
+// Current opcode (PC for debug)
+reg [31:0] ex_opcode_q;
+reg [31:0] ex_opcode_pc_q;
+
+// ALU input A
+reg [31:0] ex_alu_a_q;
+
+// ALU input B
+reg [31:0] ex_alu_b_q;
+
+// ALU output
+wire [31:0] ex_result_w;
+
+// Resolved RA/RB register contents
+wire [31:0] ra_resolved_w;
+wire [31:0] rb_resolved_w;
+wire operand_resolved_w;
+wire resolve_failed_w;
+
+// ALU Carry
+wire alu_carry_out_w;
+wire alu_carry_update_w;
+wire alu_flag_update_w;
+
+// ALU Comparisons
+wire compare_equal_w;
+wire compare_gts_w;
+wire compare_gt_w;
+wire compare_lts_w;
+wire compare_lt_w;
+
+// ALU operation selection
+reg [3:0] ex_alu_func_q;
+
+// Load instruction details
+reg [4:0] load_rd_q;
+reg [7:0] load_inst_q;
+reg [1:0] load_offset_q;
+
+// Load forwarding
+wire load_inst_w;
+wire [31:0] load_result_w;
+
+// Memory access?
+reg mem_load_q;
+reg mem_store_q;
+reg mem_access_q;
+
+wire load_pending_w;
+wire store_pending_w;
+wire load_insert_w;
+wire load_stall_w;
+
+reg d_mem_load_q;
+
+reg break_q;
+
+// Exception/Interrupt was last instruction
+reg exc_last_q;
+
+// SIM PUTC
+`ifdef SIM_EXT_PUTC
+ reg [7:0] putc_q;
+`endif
+
+//-----------------------------------------------------------------
+// ALU
+//-----------------------------------------------------------------
+altor32_alu alu
+(
+ // ALU operation select
+ .op_i(ex_alu_func_q),
+
+ // Operands
+ .a_i(ex_alu_a_q),
+ .b_i(ex_alu_b_q),
+ .c_i(sr_q[`SR_CY]),
+
+ // Result
+ .p_o(ex_result_w),
+
+ // Carry
+ .c_o(alu_carry_out_w),
+ .c_update_o(alu_carry_update_w),
+
+ // Comparisons
+ .equal_o(compare_equal_w),
+ .greater_than_signed_o(compare_gts_w),
+ .greater_than_o(compare_gt_w),
+ .less_than_signed_o(compare_lts_w),
+ .less_than_o(compare_lt_w),
+ .flag_update_o(alu_flag_update_w)
+);
+
+//-----------------------------------------------------------------
+// Load result forwarding
+//-----------------------------------------------------------------
+altor32_lfu
+u_lfu
+(
+ // Opcode
+ .opcode_i(load_inst_q),
+
+ // Memory load result
+ .mem_result_i(dmem_data_in_i),
+ .mem_offset_i(load_offset_q),
+
+ // Result
+ .load_result_o(load_result_w),
+ .load_insn_o(load_inst_w)
+);
+
+//-----------------------------------------------------------------
+// Load / store pending logic
+//-----------------------------------------------------------------
+altor32_lsu
+u_lsu
+(
+ // Current instruction
+ .opcode_valid_i(opcode_valid_i & ~pc_fetch_q),
+ .opcode_i({2'b00,opcode_i[31:26]}),
+
+ // Load / Store pending
+ .load_pending_i(mem_load_q),
+ .store_pending_i(mem_store_q),
+
+ // Load dest register
+ .rd_load_i(load_rd_q),
+
+ // Load insn in WB stage
+ .load_wb_i(d_mem_load_q),
+
+ // Memory status
+ .mem_access_i(mem_access_q),
+ .mem_ack_i(dmem_ack_i),
+
+ // Load / store still pending
+ .load_pending_o(load_pending_w),
+ .store_pending_o(store_pending_w),
+
+ // Insert load result into pipeline
+ .write_result_o(load_insert_w),
+
+ // Stall pipeline due
+ .stall_o(load_stall_w)
+);
+
+//-----------------------------------------------------------------
+// Operand forwarding
+//-----------------------------------------------------------------
+altor32_dfu
+u_dfu
+(
+ // Input registers
+ .ra_i(reg_ra_i),
+ .rb_i(reg_rb_i),
+
+ // Input register contents
+ .ra_regval_i(reg_ra_value_i),
+ .rb_regval_i(reg_rb_value_i),
+
+ // Dest register (EXEC stage)
+ .rd_ex_i(ex_rd_q),
+
+ // Dest register (WB stage)
+ .rd_wb_i(wb_rd_i),
+
+ // Load pending / target
+ .load_pending_i(load_pending_w),
+ .rd_load_i(load_rd_q),
+
+ // Multiplier status
+ .mult_ex_i(1'b0),
+
+ // Result (EXEC)
+ .result_ex_i(ex_result_w),
+
+ // Result (WB)
+ .result_wb_i(wb_rd_value_i),
+
+ // Resolved register values
+ .result_ra_o(ra_resolved_w),
+ .result_rb_o(rb_resolved_w),
+
+ // Operands required forwarding
+ .resolved_o(operand_resolved_w),
+
+ // Stall due to failed resolve
+ .stall_o(resolve_failed_w)
+);
+
+//-----------------------------------------------------------------
+// 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,opcode_i[31:26]};
+
+ // Sub instructions
+ alu_op_r = {opcode_i[9:6],opcode_i[3:0]};
+ sfxx_op_r = {5'b00,opcode_i[31:21]} & `INST_OR32_SFMASK;
+ shift_op_r = opcode_i[7:6];
+
+ // Branch target
+ target_int26_r = sign_extend_imm26(opcode_i[25:0]);
+
+ // Store immediate
+ store_int32_r = sign_extend_imm16({opcode_i[25:21],opcode_i[10:0]});
+
+ // Signed & unsigned imm -> 32-bits
+ uint16_r = opcode_i[15:0];
+ int32_r = sign_extend_imm16(opcode_i[15:0]);
+ uint32_r = extend_imm16(opcode_i[15:0]);
+
+ // Register values [ra/rb]
+ reg_ra_r = ra_resolved_w;
+ reg_rb_r = rb_resolved_w;
+
+ // Shift ammount (from register[rb])
+ shift_rb_r = {26'b00,rb_resolved_w[5:0]};
+
+ // Shift ammount (from immediate)
+ shift_imm_r = {26'b00,opcode_i[5:0]};
+
+ // MTSPR/MFSPR operand
+ // NOTE: Use unresolved register value and stall pipeline if required.
+ // This is to improve timing.
+ mxspr_uint16_r = (reg_ra_value_i[15:0] | {5'b00000,opcode_i[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_sra_w = (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_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
+wire inst_sfges_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
+
+wire inst_sfgeu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
+wire inst_sfgts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
+wire inst_sfgtu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
+wire inst_sfles_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
+wire inst_sfleu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
+wire inst_sflts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
+wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
+wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
+
+wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_SYS); // l.sys
+wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_TRAP); // l.trap
+
+//-----------------------------------------------------------------
+// Stall / Execute
+//-----------------------------------------------------------------
+reg execute_inst_r;
+reg stall_inst_r;
+
+always @ *
+begin
+ execute_inst_r = 1'b1;
+ stall_inst_r = 1'b0;
+
+ // No opcode ready or branch delay slot
+ if (~opcode_valid_i | pc_fetch_q)
+ execute_inst_r = 1'b0;
+ // Valid instruction, but load result / operand not ready
+ else if (resolve_failed_w | load_stall_w |
+ (operand_resolved_w & (inst_mfspr_w | inst_mtspr_w)))
+ stall_inst_r = 1'b1;
+end
+
+//-----------------------------------------------------------------
+// Next PC
+//-----------------------------------------------------------------
+reg [31:0] next_pc_r;
+
+always @ *
+begin
+ // Next expected PC (current PC + 4)
+ next_pc_r = (opcode_pc_i + 4);
+end
+
+//-----------------------------------------------------------------
+// Next SR
+//-----------------------------------------------------------------
+reg [31:0] next_sr_r;
+reg compare_result_r;
+always @ *
+begin
+ next_sr_r = sr_q;
+
+ // Update SR.F
+ if (alu_flag_update_w)
+ next_sr_r[`SR_F] = compare_result_r;
+
+ // Latch carry if updated
+ if (alu_carry_update_w)
+ next_sr_r[`SR_CY] = alu_carry_out_w;
+
+ // If valid instruction, check if SR needs updating
+ if (execute_inst_r & ~stall_inst_r)
+ begin
+
+ // Clear step control (if not executing higher priority syscall/break)
+ if (!inst_sys_w && !inst_trap_w)
+ next_sr_r[`SR_STEP] = 1'b0;
+
+ case (1'b1)
+ inst_mtspr_w:
+ begin
+ case (mxspr_uint16_r)
+ // SR - Supervision register
+ `SPR_REG_SR:
+ begin
+ next_sr_r = reg_rb_r;
+
+ // Don't store cache flush requests
+ next_sr_r[`SR_ICACHE_FLUSH] = 1'b0;
+ next_sr_r[`SR_DCACHE_FLUSH] = 1'b0;
+ end
+ default:
+ ;
+ endcase
+ end
+ inst_rfe_w:
+ next_sr_r = esr_q;
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Next EPC/ESR
+//-----------------------------------------------------------------
+reg [31:0] next_epc_r;
+reg [31:0] next_esr_r;
+
+always @ *
+begin
+ next_epc_r = epc_q;
+ next_esr_r = esr_q;
+ // Instruction after interrupt, update SR.F
+ if (exc_last_q && alu_flag_update_w)
+ next_esr_r[`SR_F] = compare_result_r;
+
+ // Instruction after interrupt, latch carry if updated
+ if (exc_last_q && alu_carry_update_w)
+ next_esr_r[`SR_CY] = alu_carry_out_w;
+
+ if (execute_inst_r & ~stall_inst_r)
+ begin
+ 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
+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_sra_w: // 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_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 = next_sr_r;
+ write_rd_r = 1'b1;
+ end
+
+ // EPCR - EPC Exception saved PC
+ `SPR_REG_EPCR:
+ begin
+ alu_input_a_r = epc_q;
+ write_rd_r = 1'b1;
+ end
+
+ // ESR - Exception saved SR
+ `SPR_REG_ESR:
+ begin
+ alu_input_a_r = esr_q;
+ 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;
+
+ // l.sf*i
+ inst_sfxxi_w:
+ begin
+ alu_func_r = `ALU_COMPARE;
+ alu_input_a_r = reg_ra_r;
+ alu_input_b_r = int32_r;
+ end
+
+ // l.sf*
+ inst_sfxx_w:
+ begin
+ alu_func_r = `ALU_COMPARE;
+ alu_input_a_r = reg_ra_r;
+ alu_input_b_r = reg_rb_r;
+ end
+
+ 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 (from ALU outputs)
+//-----------------------------------------------------------------
+reg inst_sfges_r;
+reg inst_sfgeu_r;
+reg inst_sfgts_r;
+reg inst_sfgtu_r;
+reg inst_sfles_r;
+reg inst_sfleu_r;
+reg inst_sflts_r;
+reg inst_sfltu_r;
+reg inst_sfne_r;
+reg inst_sfges_q;
+reg inst_sfgeu_q;
+reg inst_sfgts_q;
+reg inst_sfgtu_q;
+reg inst_sfles_q;
+reg inst_sfleu_q;
+reg inst_sflts_q;
+reg inst_sfltu_q;
+reg inst_sfne_q;
+
+always @ *
+begin
+ inst_sfges_r = 1'b0;
+ inst_sfgeu_r = 1'b0;
+ inst_sfgts_r = 1'b0;
+ inst_sfgtu_r = 1'b0;
+ inst_sfles_r = 1'b0;
+ inst_sfleu_r = 1'b0;
+ inst_sflts_r = 1'b0;
+ inst_sfltu_r = 1'b0;
+ inst_sfne_r = 1'b0;
+
+ // Valid instruction
+ if (execute_inst_r && ~stall_inst_r)
+ begin
+
+ case (1'b1)
+ inst_sfges_w: // l.sfges
+ inst_sfges_r = 1'b1;
+
+ inst_sfgeu_w: // l.sfgeu
+ inst_sfgeu_r = 1'b1;
+
+ inst_sfgts_w: // l.sfgts
+ inst_sfgts_r = 1'b1;
+
+ inst_sfgtu_w: // l.sfgtu
+ inst_sfgtu_r = 1'b1;
+
+ inst_sfles_w: // l.sfles
+ inst_sfles_r = 1'b1;
+
+ inst_sfleu_w: // l.sfleu
+ inst_sfleu_r = 1'b1;
+
+ inst_sflts_w: // l.sflts
+ inst_sflts_r = 1'b1;
+
+ inst_sfltu_w: // l.sfltu
+ inst_sfltu_r = 1'b1;
+
+ inst_sfne_w: // l.sfne
+ inst_sfne_r = 1'b1;
+
+ default:
+ ;
+ endcase
+ end
+end
+
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ inst_sfges_q <= 1'b0;
+ inst_sfgeu_q <= 1'b0;
+ inst_sfgts_q <= 1'b0;
+ inst_sfgtu_q <= 1'b0;
+ inst_sfles_q <= 1'b0;
+ inst_sfleu_q <= 1'b0;
+ inst_sflts_q <= 1'b0;
+ inst_sfltu_q <= 1'b0;
+ inst_sfne_q <= 1'b0;
+ end
+ else
+ begin
+ inst_sfges_q <= inst_sfges_r;
+ inst_sfgeu_q <= inst_sfgeu_r;
+ inst_sfgts_q <= inst_sfgts_r;
+ inst_sfgtu_q <= inst_sfgtu_r;
+ inst_sfles_q <= inst_sfles_r;
+ inst_sfleu_q <= inst_sfleu_r;
+ inst_sflts_q <= inst_sflts_r;
+ inst_sfltu_q <= inst_sfltu_r;
+ inst_sfne_q <= inst_sfne_r;
+ end
+end
+
+always @ *
+begin
+ case (1'b1)
+ inst_sfges_q: // l.sfges
+ compare_result_r = compare_gts_w | compare_equal_w;
+
+ inst_sfgeu_q: // l.sfgeu
+ compare_result_r = compare_gt_w | compare_equal_w;
+
+ inst_sfgts_q: // l.sfgts
+ compare_result_r = compare_gts_w;
+
+ inst_sfgtu_q: // l.sfgtu
+ compare_result_r = compare_gt_w;
+
+ inst_sfles_q: // l.sfles
+ compare_result_r = compare_lts_w | compare_equal_w;
+
+ inst_sfleu_q: // l.sfleu
+ compare_result_r = compare_lt_w | compare_equal_w;
+
+ inst_sflts_q: // l.sflts
+ compare_result_r = compare_lts_w;
+
+ inst_sfltu_q: // l.sfltu
+ compare_result_r = compare_lt_w;
+
+ inst_sfne_q: // l.sfne
+ compare_result_r = ~compare_equal_w;
+
+ default: // l.sfeq
+ compare_result_r = compare_equal_w;
+ endcase
+end
+
+//-----------------------------------------------------------------
+// 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
+
+//-----------------------------------------------------------------
+// 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 = (opcode_pc_i + {target_int26_r[29:0],2'b00});
+
+ case (1'b1)
+ inst_bf_w: // l.bf
+ branch_r = next_sr_r[`SR_F];
+
+ inst_bnf_w: // l.bnf
+ branch_r = ~next_sr_r[`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 = epc_q;
+ 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_sra_w,
+ 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_sfges_w,
+ inst_sfgeu_w,
+ inst_sfgts_w,
+ inst_sfgtu_w,
+ inst_sfles_w,
+ inst_sfleu_w,
+ inst_sflts_w,
+ inst_sfltu_w,
+ inst_sfne_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
+ ex_alu_func_q <= `ALU_NONE;
+ ex_alu_a_q <= 32'h00000000;
+ ex_alu_b_q <= 32'h00000000;
+ ex_rd_q <= 5'b00000;
+ end
+ else
+ begin
+ //---------------------------------------------------------------
+ // Instruction not ready
+ //---------------------------------------------------------------
+ if (~execute_inst_r | stall_inst_r)
+ begin
+ // Insert load result?
+ if (load_insert_w)
+ begin
+ // Feed load result into pipeline
+ ex_alu_func_q <= `ALU_NONE;
+ ex_alu_a_q <= load_result_w;
+ ex_alu_b_q <= 32'b0;
+ ex_rd_q <= load_rd_q;
+ end
+ else
+ begin
+ // No ALU operation (output == input_a)
+ ex_alu_func_q <= `ALU_NONE;
+ ex_alu_a_q <= 32'b0;
+ ex_alu_b_q <= 32'b0;
+ ex_rd_q <= 5'b0;
+ end
+ end
+ //---------------------------------------------------------------
+ // Valid instruction
+ //---------------------------------------------------------------
+ else
+ begin
+ // Update ALU input flops
+ ex_alu_func_q <= alu_func_r;
+ ex_alu_a_q <= alu_input_a_r;
+ ex_alu_b_q <= alu_input_b_r;
+
+ // Branch and link (Rd = LR/R9)
+ if (branch_link_r)
+ ex_rd_q <= 5'd9;
+ // Instruction with register writeback
+ else if (write_rd_r)
+ ex_rd_q <= reg_rd_i;
+ else
+ ex_rd_q <= 5'b0;
+ end
+ end
+end
+
+//-----------------------------------------------------------------
+// Execute: Update executed PC / opcode
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ ex_opcode_q <= 32'h00000000;
+ ex_opcode_pc_q <= 32'h00000000;
+ end
+ else
+ begin
+ // Instruction not ready
+ if (~execute_inst_r | stall_inst_r)
+ begin
+ // Store bubble opcode
+ ex_opcode_q <= `OPCODE_INST_BUBBLE;
+ ex_opcode_pc_q <= opcode_pc_i;
+ end
+ // Valid instruction
+ else
+ begin
+ // Store opcode
+ ex_opcode_q <= opcode_i;
+ ex_opcode_pc_q <= opcode_pc_i;
+
+ `ifdef CONF_CORE_TRACE
+ $display("%08x: Execute 0x%08x", opcode_pc_i, opcode_i);
+ $display(" rA[%d] = 0x%08x", reg_ra_i, reg_ra_r);
+ $display(" rB[%d] = 0x%08x", reg_rb_i, reg_rb_r);
+ `endif
+ end
+ end
+end
+
+//-----------------------------------------------------------------
+// Execute: Branch / exceptions
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ pc_branch_q <= 32'h00000000;
+ pc_fetch_q <= 1'b0;
+ exc_last_q <= 1'b0;
+
+ // Status registers
+ epc_q <= 32'h00000000;
+ sr_q <= 32'h00000000;
+ esr_q <= 32'h00000000;
+
+ fault_o <= 1'b0;
+
+ break_q <= 1'b0;
+ break_o <= 1'b0;
+ end
+ else
+ begin
+ // Flop break request, clear when break interrupt executed
+ if (break_i)
+ break_q <= 1'b1;
+
+ // Reset branch request
+ pc_fetch_q <= 1'b0;
+ exc_last_q <= 1'b0;
+
+ break_o <= 1'b0;
+
+ // Update SR
+ sr_q <= next_sr_r;
+
+ // Update EPC / ESR which may have been updated by an
+ // MTSPR write / flag update in instruction after interrupt
+ epc_q <= next_epc_r;
+ esr_q <= next_esr_r;
+
+ // Instruction ready
+ if (execute_inst_r & ~stall_inst_r)
+ begin
+ // Exception: Instruction opcode not valid / supported, invalid PC
+ if (invalid_inst_r || (opcode_pc_i[1:0] != 2'b00))
+ begin
+ // Save PC of next instruction
+ epc_q <= next_pc_r;
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts
+ sr_q <= 32'b0;
+
+ // Set PC to exception vector
+ if (invalid_inst_r)
+ pc_branch_q <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
+ else
+ pc_branch_q <= ISR_VECTOR + `VECTOR_BUS_ERROR;
+ pc_fetch_q <= 1'b1;
+ exc_last_q <= 1'b1;
+
+ fault_o <= 1'b1;
+ end
+ // Exception: Syscall / Break
+ else if (branch_except_r)
+ begin
+ // Save PC of next instruction
+ epc_q <= next_pc_r;
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts / break events
+ sr_q <= 32'b0;
+
+ // Set PC to exception vector
+ pc_branch_q <= branch_target_r;
+ pc_fetch_q <= 1'b1;
+ exc_last_q <= 1'b1;
+
+ if (inst_trap_w)
+ break_o <= 1'b1;
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Exception 0x%08x", branch_target_r);
+ `endif
+ end
+ // Single step / break request
+ else if ((sr_q[`SR_STEP] || break_q) && sr_q[`SR_DBGEN])
+ begin
+ // Save PC of next instruction
+ if (branch_r)
+ epc_q <= branch_target_r;
+ // Next expected PC (current PC + 4)
+ else
+ epc_q <= next_pc_r;
+
+ // Save SR
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts / break events
+ sr_q <= 32'b0;
+ break_q <= 1'b0;
+ break_o <= 1'b1;
+
+ // Set PC to trap vector
+ pc_branch_q <= ISR_VECTOR + `VECTOR_TRAP;
+ pc_fetch_q <= 1'b1;
+ exc_last_q <= 1'b1;
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Break Event 0x%08x", ISR_VECTOR + `VECTOR_TRAP);
+ `endif
+ end
+ // External interrupt
+ else if (intr_i && next_sr_r[`SR_IEE])
+ begin
+ // Save PC of next instruction & SR
+ if (branch_r)
+ epc_q <= branch_target_r;
+ // Next expected PC (current PC + 4)
+ else
+ epc_q <= next_pc_r;
+
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts / break events
+ sr_q <= 32'b0;
+
+ // Set PC to external interrupt vector
+ pc_branch_q <= ISR_VECTOR + `VECTOR_EXTINT;
+ pc_fetch_q <= 1'b1;
+ exc_last_q <= 1'b1;
+
+ `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
+ pc_branch_q <= branch_target_r;
+ pc_fetch_q <= 1'b1;
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Branch to 0x%08x", branch_target_r);
+ `endif
+ end
+ end
+ end
+end
+
+//-----------------------------------------------------------------
+// Execute: Memory operations
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ // Data memory
+ dmem_addr_o <= 32'h00000000;
+ dmem_data_out_o <= 32'h00000000;
+ dmem_we_o <= 1'b0;
+ dmem_sel_o <= 4'b0000;
+ dmem_stb_o <= 1'b0;
+ dmem_cyc_o <= 1'b0;
+
+ mem_load_q <= 1'b0;
+ mem_store_q <= 1'b0;
+ mem_access_q <= 1'b0;
+
+ load_rd_q <= 5'b00000;
+ load_inst_q <= 8'h00;
+ load_offset_q <= 2'b00;
+
+ d_mem_load_q <= 1'b0;
+ end
+ else
+ begin
+
+ // If memory access accepted by slave
+ if (~dmem_stall_i)
+ dmem_stb_o <= 1'b0;
+
+ if (dmem_ack_i)
+ dmem_cyc_o <= 1'b0;
+
+ mem_access_q <= 1'b0;
+ d_mem_load_q <= mem_access_q & mem_load_q;
+
+ // Pending accesses
+ mem_load_q <= load_pending_w;
+ mem_store_q <= store_pending_w;
+
+ //---------------------------------------------------------------
+ // Valid instruction
+ //---------------------------------------------------------------
+ if (execute_inst_r & ~stall_inst_r)
+ begin
+ // Branch and link (Rd = LR/R9)
+ if (branch_link_r)
+ begin
+ // Load outstanding, check if result target is being
+ // overwritten (to avoid WAR hazard)
+ if (load_rd_q == 5'd9)
+ // Ditch load result when it arrives
+ load_rd_q <= 5'b00000;
+ end
+ // Instruction with register writeback
+ else if (write_rd_r)
+ begin
+ // Load outstanding, check if result target is being
+ // overwritten (to avoid WAR hazard)
+ if (reg_rd_i == load_rd_q && ~load_inst_r)
+ // Ditch load result when it arrives
+ load_rd_q <= 5'b00000;
+ end
+
+ case (1'b1)
+
+ // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
+ load_inst_r:
+ begin
+ dmem_addr_o <= mem_addr_r;
+ dmem_data_out_o <= 32'h00000000;
+ dmem_sel_o <= 4'b1111;
+ dmem_we_o <= 1'b0;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+
+ // Mark load as pending
+ mem_load_q <= 1'b1;
+ mem_access_q <= 1'b1;
+
+ // Record target register
+ load_rd_q <= reg_rd_i;
+ load_inst_q <= inst_r;
+ load_offset_q <= mem_addr_r[1:0];
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Load from 0x%08x to R%d", mem_addr_r, reg_rd_i);
+ `endif
+ end
+
+ inst_sb_w: // l.sb
+ begin
+ dmem_addr_o <= mem_addr_r;
+ mem_access_q <= 1'b1;
+ case (mem_addr_r[1:0])
+ 2'b00 :
+ begin
+ dmem_data_out_o <= {reg_rb_r[7:0],24'h000000};
+ dmem_sel_o <= 4'b1000;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_store_q <= 1'b1;
+ end
+ 2'b01 :
+ begin
+ dmem_data_out_o <= {{8'h00,reg_rb_r[7:0]},16'h0000};
+ dmem_sel_o <= 4'b0100;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_store_q <= 1'b1;
+ end
+ 2'b10 :
+ begin
+ dmem_data_out_o <= {{16'h0000,reg_rb_r[7:0]},8'h00};
+ dmem_sel_o <= 4'b0010;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_store_q <= 1'b1;
+ end
+ 2'b11 :
+ begin
+ dmem_data_out_o <= {24'h000000,reg_rb_r[7:0]};
+ dmem_sel_o <= 4'b0001;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_store_q <= 1'b1;
+ end
+ default :
+ ;
+ endcase
+ end
+
+ inst_sh_w: // l.sh
+ begin
+ dmem_addr_o <= mem_addr_r;
+ mem_access_q <= 1'b1;
+ case (mem_addr_r[1:0])
+ 2'b00 :
+ begin
+ dmem_data_out_o <= {reg_rb_r[15:0],16'h0000};
+ dmem_sel_o <= 4'b1100;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_store_q <= 1'b1;
+ end
+ 2'b10 :
+ begin
+ dmem_data_out_o <= {16'h0000,reg_rb_r[15:0]};
+ dmem_sel_o <= 4'b0011;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_store_q <= 1'b1;
+ end
+ default :
+ ;
+ endcase
+ end
+
+ inst_sw_w: // l.sw
+ begin
+ dmem_addr_o <= mem_addr_r;
+ dmem_data_out_o <= reg_rb_r;
+ dmem_sel_o <= 4'b1111;
+ dmem_we_o <= 1'b1;
+ dmem_stb_o <= 1'b1;
+ dmem_cyc_o <= 1'b1;
+ mem_access_q <= 1'b1;
+ mem_store_q <= 1'b1;
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Store R%d to 0x%08x = 0x%08x", reg_rb_i, {mem_addr_r[31:2],2'b00}, reg_rb_r);
+ `endif
+ end
+ default:
+ ;
+ endcase
+ end
+ end
+end
+
+//-----------------------------------------------------------------
+// Execute: Misc operations
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ icache_flush_o <= 1'b0;
+ dcache_flush_o <= 1'b0;
+ end
+ else
+ begin
+ icache_flush_o <= 1'b0;
+ dcache_flush_o <= 1'b0;
+
+ //---------------------------------------------------------------
+ // Valid instruction
+ //---------------------------------------------------------------
+ if (execute_inst_r & ~stall_inst_r)
+ begin
+ case (1'b1)
+ inst_mtspr_w: // l.mtspr
+ begin
+ case (mxspr_uint16_r)
+ // SR - Supervision register
+ `SPR_REG_SR:
+ begin
+ // Cache flush request?
+ icache_flush_o <= reg_rb_r[`SR_ICACHE_FLUSH];
+ dcache_flush_o <= reg_rb_r[`SR_DCACHE_FLUSH];
+ end
+ endcase
+ end
+ default:
+ ;
+ endcase
+ end
+ 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
+ putc_q <= 8'b0;
+ `endif
+ end
+ else
+ begin
+ `ifdef SIM_EXT_PUTC
+ putc_q <= 8'b0;
+ `endif
+ //---------------------------------------------------------------
+ // Valid instruction
+ //---------------------------------------------------------------
+ if (execute_inst_r & ~stall_inst_r)
+ begin
+
+ case (1'b1)
+ inst_nop_w: // l.nop
+ begin
+ case (uint16_r)
+ // NOP_PUTC
+ 16'h0004:
+ begin
+ `ifdef SIM_EXT_PUTC
+ putc_q <= reg_ra_r[7:0];
+ `else
+ $write("%c", reg_ra_r[7:0]);
+ `endif
+ end
+ // NOP
+ 16'h0000: ;
+ endcase
+ end
+ default:
+ ;
+ endcase
+ end
+ end
+ end
+`endif
+
+//-------------------------------------------------------------------
+// Assignments
+//-------------------------------------------------------------------
+
+assign branch_pc_o = pc_branch_q;
+assign branch_o = pc_fetch_q;
+assign stall_o = stall_inst_r;
+
+assign opcode_o = ex_opcode_q;
+assign opcode_pc_o = ex_opcode_pc_q;
+
+assign reg_rd_o = ex_rd_q;
+assign reg_rd_value_o = ex_result_w;
+
+assign mult_res_o = 64'b0;
+
+//-------------------------------------------------------------------
+// Hooks for debug
+//-------------------------------------------------------------------
+`ifdef verilator
+ function [31:0] get_opcode_ex;
+ // verilator public
+ get_opcode_ex = ex_opcode_q;
+ endfunction
+ function [31:0] get_pc_ex;
+ // verilator public
+ get_pc_ex = ex_opcode_pc_q;
+ endfunction
+ function [7:0] get_putc;
+ // verilator public
+ `ifdef SIM_EXT_PUTC
+ get_putc = putc_q;
+ `else
+ get_putc = 8'b0;
+ `endif
+ endfunction
+ function [0:0] get_reg_valid;
+ // verilator public
+ get_reg_valid = ~(resolve_failed_w | load_stall_w | ~opcode_valid_i);
+ endfunction
+ function [4:0] get_reg_ra;
+ // verilator public
+ get_reg_ra = reg_ra_i;
+ endfunction
+ function [31:0] get_reg_ra_value;
+ // verilator public
+ get_reg_ra_value = ra_resolved_w;
+ endfunction
+ function [4:0] get_reg_rb;
+ // verilator public
+ get_reg_rb = reg_rb_i;
+ endfunction
+ function [31:0] get_reg_rb_value;
+ // verilator public
+ get_reg_rb_value = rb_resolved_w;
+ endfunction
+`endif
+
+endmodule
altor32/rtl/cpu/altor32_exec.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_fetch.v
===================================================================
--- altor32/rtl/cpu/altor32_fetch.v (nonexistent)
+++ altor32/rtl/cpu/altor32_fetch.v (revision 25)
@@ -0,0 +1,213 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module - Instruction Fetch
+//-----------------------------------------------------------------
+module altor32_fetch
+(
+ // General
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Instruction Fetch
+ output fetch_o /*verilator public*/,
+ output reg [31:0] pc_o /*verilator public*/,
+ input [31:0] data_i /*verilator public*/,
+ input data_valid_i/*verilator public*/,
+
+ // Branch target
+ input branch_i /*verilator public*/,
+ input [31:0] branch_pc_i /*verilator public*/,
+ input stall_i /*verilator public*/,
+
+ // Decoded opcode
+ output [31:0] opcode_o /*verilator public*/,
+ output [31:0] opcode_pc_o /*verilator public*/,
+ output opcode_valid_o /*verilator public*/,
+
+ // Decoded register details
+ output [4:0] ra_o /*verilator public*/,
+ output [4:0] rb_o /*verilator public*/,
+ output [4:0] rd_o /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter BOOT_VECTOR = 32'h00000000;
+parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
+parameter PIPELINED_FETCH = "DISABLED";
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+reg rd_q;
+reg [31:0] pc_q;
+reg [31:0] pc_last_q;
+
+//-------------------------------------------------------------------
+// Next PC state machine
+//-------------------------------------------------------------------
+wire [31:0] next_pc_w = pc_q + 32'd4;
+
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i)
+ begin
+ pc_q <= BOOT_VECTOR + `VECTOR_RESET;
+ pc_last_q <= BOOT_VECTOR + `VECTOR_RESET;
+ rd_q <= 1'b1;
+ end
+ else if (~stall_i)
+ begin
+ // Branch - Next PC = branch target + 4
+ if (branch_i)
+ begin
+ rd_q <= 1'b0;
+ pc_last_q <= pc_o;
+ pc_q <= branch_pc_i + 4;
+ end
+ // Normal sequential execution (and instruction is ready)
+ else if (data_valid_i)
+ begin
+ // New cache line?
+ if (next_pc_w[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
+ rd_q <= 1'b1;
+ else
+ rd_q <= 1'b0;
+
+ pc_last_q <= pc_o;
+ pc_q <= next_pc_w;
+ end
+ else
+ begin
+ rd_q <= 1'b0;
+ pc_last_q <= pc_o;
+ end
+ end
+end
+
+//-------------------------------------------------------------------
+// Instruction Fetch
+//-------------------------------------------------------------------
+always @ *
+begin
+ // Stall, revert to last requested PC
+ if (stall_i)
+ pc_o = pc_last_q;
+ else if (branch_i)
+ pc_o = branch_pc_i;
+ else if (~data_valid_i)
+ pc_o = pc_last_q;
+ else
+ pc_o = pc_q;
+end
+
+assign fetch_o = branch_i ? 1'b1 : rd_q;
+
+//-------------------------------------------------------------------
+// Opcode output (retiming)
+//-------------------------------------------------------------------
+generate
+if (PIPELINED_FETCH == "ENABLED")
+begin: FETCH_FLOPS
+ reg [31:0] opcode_q;
+ reg [31:0] opcode_pc_q;
+ reg opcode_valid_q;
+ reg branch_q;
+
+ always @ (posedge clk_i or posedge rst_i)
+ begin
+ if (rst_i)
+ begin
+ opcode_q <= 32'b0;
+ opcode_pc_q <= 32'b0;
+ opcode_valid_q <= 1'b0;
+ branch_q <= 1'b0;
+ end
+ else
+ begin
+ branch_q <= branch_i;
+
+ if (~stall_i)
+ begin
+ opcode_pc_q <= pc_last_q;
+ opcode_q <= data_i;
+ opcode_valid_q <= (data_valid_i & !branch_i);
+ end
+ end
+ end
+
+ // Opcode output
+ assign opcode_valid_o = opcode_valid_q & ~branch_i & ~branch_q;
+ assign opcode_o = opcode_q;
+ assign opcode_pc_o = opcode_pc_q;
+end
+//-------------------------------------------------------------------
+// Opcode output
+//-------------------------------------------------------------------
+else
+begin : NO_FETCH_FLOPS
+ assign opcode_valid_o = (data_valid_i & !branch_i);
+ assign opcode_o = data_i;
+ assign opcode_pc_o = pc_last_q;
+end
+endgenerate
+
+//-------------------------------------------------------------------
+// Opcode output
+//-------------------------------------------------------------------
+// If simulation, RA = 03 if NOP instruction
+`ifdef SIMULATION
+ wire [7:0] fetch_inst_w = {2'b00, opcode_o[31:26]};
+ wire nop_inst_w = (fetch_inst_w == `INST_OR32_NOP);
+ assign ra_o = nop_inst_w ? 5'd3 : opcode_o[20:16];
+`else
+ assign ra_o = opcode_o[20:16];
+`endif
+
+assign rb_o = opcode_o[15:11];
+assign rd_o = opcode_o[25:21];
+
+endmodule
altor32/rtl/cpu/altor32_fetch.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_funcs.v
===================================================================
--- altor32/rtl/cpu/altor32_funcs.v (nonexistent)
+++ altor32/rtl/cpu/altor32_funcs.v (revision 25)
@@ -0,0 +1,259 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+
+`ifdef ADD_FUNCTION
+`undef ADD_FUNCTION
+
+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
+
+`endif
altor32/rtl/cpu/altor32_funcs.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_icache.v
===================================================================
--- altor32/rtl/cpu/altor32_icache.v (nonexistent)
+++ altor32/rtl/cpu/altor32_icache.v (revision 25)
@@ -0,0 +1,622 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module - Instruction Cache
+//-----------------------------------------------------------------
+module altor32_icache
+(
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Processor interface
+ input rd_i /*verilator public*/,
+ input [31:0] pc_i /*verilator public*/,
+ output [31:0] instruction_o /*verilator public*/,
+ output valid_o /*verilator public*/,
+ input invalidate_i /*verilator public*/,
+
+ // Memory interface
+ output [31:0] wbm_addr_o /*verilator public*/,
+ input [31:0] wbm_dat_i /*verilator public*/,
+ output [2:0] wbm_cti_o /*verilator public*/,
+ output wbm_cyc_o /*verilator public*/,
+ output wbm_stb_o /*verilator public*/,
+ input wbm_stall_i/*verilator public*/,
+ input wbm_ack_i/*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter BOOT_VECTOR = 32'h00000000;
+
+// Option: Number of ways (supports 1 or 2)
+parameter CACHE_NUM_WAYS = 1;
+
+// Option: Number of cache lines (2^param) * line_size_bytes = cache size
+parameter CACHE_LINE_ADDR_WIDTH = 8 - (CACHE_NUM_WAYS-1); /* 256 lines total across all ways */
+
+parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
+parameter CACHE_LINE_SIZE_BYTES = 2 ** CACHE_LINE_SIZE_WIDTH; /* 32 bytes / 8 words per line */
+
+parameter CACHE_TAG_ENTRIES = 2 ** CACHE_LINE_ADDR_WIDTH ; /* 128 tag entries */
+parameter CACHE_DSIZE = CACHE_NUM_WAYS * (2 ** CACHE_LINE_ADDR_WIDTH) * CACHE_LINE_SIZE_BYTES; /* 8KB data */
+parameter CACHE_DWIDTH = CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 2; /* 10-bits */
+
+parameter CACHE_TAG_WIDTH = 16; /* 16-bit tag entry size */
+parameter CACHE_TAG_STAT_BITS = 1 + (CACHE_NUM_WAYS-1);
+
+parameter CACHE_TAG_LINE_ADDR_WIDTH = CACHE_TAG_WIDTH - CACHE_TAG_STAT_BITS; /* 15 bits of data (tag entry size minus valid / LRU bit) */
+
+parameter CACHE_TAG_ADDR_LOW = CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH;
+parameter CACHE_TAG_ADDR_HIGH = CACHE_TAG_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH - 1;
+
+// Tag fields
+parameter CACHE_TAG_VALID_BIT = 15;
+parameter CACHE_TAG_LRU_BIT = 14; // If CACHE_NUM_WAYS > 1
+parameter CACHE_TAG_ADDR_BITS = CACHE_TAG_WIDTH - CACHE_TAG_STAT_BITS;
+
+// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+// |--------------| | | | | | | | | | | | | | | | |
+// +-----------------+ +-------------------+ +-----------+
+// Tag entry Line address Address
+// (14/15-bits) (7/8-bits) within line
+// (5-bits)
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+// Tag read / write data
+reg tag_wr_r;
+wire [CACHE_TAG_WIDTH-1:0] tag_out0_w;
+reg [CACHE_TAG_WIDTH-1:0] tag_in0_r;
+wire [CACHE_TAG_WIDTH-1:0] tag_out1_w;
+reg [CACHE_TAG_WIDTH-1:0] tag_in1_r;
+
+// Tag address
+wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_address_w;
+
+// Data memory read / write
+wire [CACHE_DWIDTH-1:0] address_rd_w;
+wire [CACHE_DWIDTH-1:0] address_wr_w;
+
+wire cache_wr0_w;
+wire cache_wr1_w;
+
+reg way_update_q;
+
+// Current / Miss PC
+reg [31:0] last_pc_q;
+reg [31:0] miss_pc_q;
+
+// Flush state
+reg flush_q;
+reg [CACHE_LINE_ADDR_WIDTH-1:0] flush_addr_q;
+reg flush_wr_q;
+
+// Other state
+reg read_while_busy_q;
+
+// Current state
+parameter STATE_CHECK = 0;
+parameter STATE_FETCH = 1;
+parameter STATE_WAIT = 2;
+parameter STATE_FLUSH = 3;
+reg [1:0] state_q;
+
+// Tag address from input PC or flopped version of it
+assign tag_address_w = (state_q != STATE_CHECK) ?
+ miss_pc_q[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] :
+ pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
+
+// Cache read address
+assign address_rd_w = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2];
+
+// Cache miss output if requested PC is not in the tag memory
+wire miss0_w = ~tag_out0_w[CACHE_TAG_VALID_BIT] |
+ (last_pc_q[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_out0_w[CACHE_TAG_ADDR_BITS-1:0]);
+
+wire miss1_w = ~tag_out1_w[CACHE_TAG_VALID_BIT] |
+ (last_pc_q[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_out1_w[CACHE_TAG_ADDR_BITS-1:0]);
+
+// Stall the CPU if cache state machine is not idle!
+wire busy_w = (state_q != STATE_CHECK) | read_while_busy_q;
+
+// Cache output valid
+assign valid_o = busy_w ? 1'b0 : ~(miss0_w & miss1_w);
+
+// Flushing: Last line to flush
+wire flush_last_w = (flush_addr_q == {CACHE_LINE_ADDR_WIDTH{1'b0}});
+
+// Is this a cache miss?
+wire cache_miss_w = miss0_w & miss1_w & // Tag lookup failed
+ !rd_i & // NOT new read request cycle
+ !read_while_busy_q & // NOT pending read whilst busy
+ !flush_q & // NOT flush request
+ !invalidate_i;
+
+wire mem_fetch_w = (state_q == STATE_CHECK) & cache_miss_w;
+wire [31:0] mem_data_w;
+wire [31:0] mem_resp_addr_w;
+wire mem_valid_w;
+wire mem_final_w;
+
+//-----------------------------------------------------------------
+// Next State Logic
+//-----------------------------------------------------------------
+reg [1:0] next_state_r;
+always @ *
+begin
+ next_state_r = state_q;
+
+ case (state_q)
+
+ //-----------------------------------------
+ // CHECK - check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache flush request pending?
+ if (flush_q || invalidate_i)
+ next_state_r = STATE_FLUSH;
+ // Cache miss (& new read request not pending)
+ else if (cache_miss_w)
+ next_state_r = STATE_FETCH;
+ // Cache hit (or new read request)
+ else
+ next_state_r = STATE_CHECK;
+ end
+ //-----------------------------------------
+ // FETCH - Fetch row from memory
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Line fetch complete?
+ if (mem_final_w)
+ next_state_r = STATE_WAIT;
+ end
+ //-----------------------------------------
+ // FLUSH - Invalidate tag memory
+ //-----------------------------------------
+ STATE_FLUSH :
+ begin
+ if (flush_last_w)
+ next_state_r = STATE_CHECK;
+ else
+ next_state_r = STATE_FLUSH;
+ end
+ //-----------------------------------------
+ // WAIT - Wait cycle
+ //-----------------------------------------
+ STATE_WAIT :
+ next_state_r = STATE_CHECK;
+ default:
+ ;
+ endcase
+end
+
+// Update state
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ state_q <= STATE_FLUSH;
+ else
+ state_q <= next_state_r;
+end
+
+//-----------------------------------------------------------------
+// Select way to be replaced
+//-----------------------------------------------------------------
+reg lru_way_r;
+
+// 2-Way
+generate
+if (CACHE_NUM_WAYS >= 2)
+begin: LRU_SELECT
+ always @ *
+ begin
+ if (tag_out0_w[CACHE_TAG_LRU_BIT])
+ lru_way_r = 1'b0;
+ else
+ lru_way_r = 1'b1;
+ end
+end
+// 1-Way
+else
+begin: LRU_FIXED
+ wire lru_way_w = 1'b0;
+ always @ *
+ lru_way_r = lru_way_w;
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Flop request details
+//-----------------------------------------------------------------
+reg [CACHE_LINE_ADDR_WIDTH-1:0] tag_address_q;
+
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ miss_pc_q <= BOOT_VECTOR + `VECTOR_RESET;
+ last_pc_q <= 32'h00000000;
+
+ tag_address_q <= {CACHE_LINE_ADDR_WIDTH{1'b0}};
+ way_update_q <= 1'b0;
+ end
+ else
+ begin
+ last_pc_q <= pc_i;
+ tag_address_q <= tag_address_w;
+
+ case (state_q)
+
+ //-----------------------------------------
+ // CHECK - check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache hit (or new read request), store fetch PC
+ if (!cache_miss_w)
+ begin
+ miss_pc_q <= pc_i;
+ end
+ // Cache miss
+ else
+ begin
+ // Select line way to replace
+ way_update_q <= lru_way_r;
+ end
+ end
+ default:
+ ;
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Detect new read request whilst busy
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ read_while_busy_q <= 1'b0;
+ end
+ else
+ begin
+ case (state_q)
+ //-----------------------------------------
+ // CHECK - Check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ read_while_busy_q <= 1'b0;
+ end
+ //-----------------------------------------
+ // OTHER - Fetching, flushing, waiting
+ //-----------------------------------------
+ default:
+ begin
+ // New request whilst cache busy?
+ if (rd_i)
+ read_while_busy_q <= 1'b1;
+ end
+ endcase
+ end
+end
+
+//-----------------------------------------------------------------
+// Cache Tag Write
+//-----------------------------------------------------------------
+always @ *
+begin
+ tag_in0_r = tag_out0_w;
+ tag_in1_r = tag_out1_w;
+ tag_wr_r = 1'b0;
+
+ case (state_q)
+
+ //-----------------------------------------
+ // CHECK - check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache miss (& new read request not pending)
+ if (cache_miss_w)
+ begin
+ // Update tag memory with this line's details
+ if (lru_way_r)
+ begin
+ tag_in1_r[CACHE_TAG_ADDR_BITS-1:0] = miss_pc_q[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW];
+ tag_in1_r[CACHE_TAG_VALID_BIT] = 1'b1;
+
+ if (CACHE_NUM_WAYS >= 2)
+ begin
+ tag_in1_r[CACHE_TAG_LRU_BIT] = 1'b0;
+ tag_in0_r[CACHE_TAG_LRU_BIT] = 1'b1;
+ end
+ end
+ else
+ begin
+ tag_in0_r[CACHE_TAG_ADDR_BITS-1:0] = miss_pc_q[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW];
+ tag_in0_r[CACHE_TAG_VALID_BIT] = 1'b1;
+
+ if (CACHE_NUM_WAYS >= 2)
+ begin
+ tag_in0_r[CACHE_TAG_LRU_BIT] = 1'b0;
+ tag_in1_r[CACHE_TAG_LRU_BIT] = 1'b1;
+ end
+ end
+
+ tag_wr_r = 1'b1;
+ end
+ // Update LRU (if possible)
+ else if ((tag_address_q == tag_address_w) && (CACHE_NUM_WAYS >= 2))
+ begin
+ // Hit Way 0
+ if (!miss0_w)
+ begin
+ // Least recently used way is 1
+ tag_in1_r[CACHE_TAG_LRU_BIT] = 1'b1;
+ tag_in0_r[CACHE_TAG_LRU_BIT] = 1'b0;
+ end
+ // Hit Way 1
+ else
+ begin
+ // Least recently used way is 0
+ tag_in0_r[CACHE_TAG_LRU_BIT] = 1'b1;
+ tag_in1_r[CACHE_TAG_LRU_BIT] = 1'b0;
+ end
+
+ tag_wr_r = 1'b1;
+ end
+ end
+ default:
+ ;
+ endcase
+end
+
+//-----------------------------------------------------------------
+// Flush Logic
+//-----------------------------------------------------------------
+reg flush_r;
+reg [CACHE_LINE_ADDR_WIDTH-1:0] flush_addr_r;
+reg flush_wr_r;
+
+always @ *
+begin
+ flush_wr_r = 1'b0;
+ flush_addr_r = flush_addr_q;
+ flush_r = flush_q;
+
+ case (state_q)
+
+ //-----------------------------------------
+ // CHECK - Check cache for hit or miss
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ // Cache flush request pending?
+ if (flush_q || invalidate_i)
+ begin
+ flush_r = 1'b0;
+ flush_addr_r = {CACHE_LINE_ADDR_WIDTH{1'b1}};
+ flush_wr_r = 1'b1;
+ end
+ end
+ //-----------------------------------------
+ // FLUSH - Invalidate tag memory
+ //-----------------------------------------
+ STATE_FLUSH :
+ begin
+ flush_addr_r = flush_addr_q - 1;
+ flush_wr_r = 1'b1;
+ end
+ //-----------------------------------------
+ // OTHER - Fetching / wait cycles
+ //-----------------------------------------
+ default:
+ begin
+ // Latch invalidate request even if can't be actioned now...
+ if (invalidate_i)
+ flush_r = 1'b1;
+ end
+ endcase
+end
+
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ flush_addr_q <= {CACHE_LINE_ADDR_WIDTH{1'b1}};
+ flush_wr_q <= 1'b0;
+ flush_q <= 1'b0;
+ end
+ else
+ begin
+ flush_addr_q <= flush_addr_r;
+ flush_wr_q <= flush_wr_r;
+ flush_q <= flush_r;
+ end
+end
+
+//-----------------------------------------------------------------
+// External Mem Access
+//-----------------------------------------------------------------
+altor32_wb_fetch
+u_wb
+(
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ // Request
+ .fetch_i(mem_fetch_w),
+ .burst_i(1'b1),
+ .address_i(miss_pc_q),
+
+ // Response
+ .resp_addr_o(mem_resp_addr_w),
+ .data_o(mem_data_w),
+ .valid_o(mem_valid_w),
+ .final_o(mem_final_w),
+
+ // Wishbone interface
+ .wbm_addr_o(wbm_addr_o),
+ .wbm_dat_i(wbm_dat_i),
+ .wbm_cti_o(wbm_cti_o),
+ .wbm_cyc_o(wbm_cyc_o),
+ .wbm_stb_o(wbm_stb_o),
+ .wbm_stall_i(wbm_stall_i),
+ .wbm_ack_i(wbm_ack_i)
+);
+
+//-----------------------------------------------------------------
+// Tag memory
+//-----------------------------------------------------------------
+wire [(CACHE_NUM_WAYS*CACHE_TAG_WIDTH)-1:0] tag_in;
+wire [(CACHE_NUM_WAYS*CACHE_TAG_WIDTH)-1:0] tag_out;
+
+altor32_ram_dp
+#(
+ .WIDTH(CACHE_TAG_WIDTH * CACHE_NUM_WAYS),
+ .SIZE(CACHE_LINE_ADDR_WIDTH)
+)
+u_tag_mem
+(
+ // Tag read/write port
+ .aclk_i(clk_i),
+ .adat_o(tag_out),
+ .adat_i(tag_in),
+ .aadr_i(tag_address_w),
+ .awr_i(tag_wr_r),
+
+ // Tag invalidate port
+ .bclk_i(clk_i),
+ .badr_i(flush_addr_q),
+ .bdat_o(/*open*/),
+ .bdat_i({(CACHE_NUM_WAYS*CACHE_TAG_WIDTH){1'b0}}),
+ .bwr_i(flush_wr_q)
+);
+
+// 2-Way
+generate
+if (CACHE_NUM_WAYS >= 2)
+begin: TAG_2WAY
+ assign tag_in = {tag_in1_r, tag_in0_r};
+ assign {tag_out1_w, tag_out0_w} = tag_out;
+end
+// 1-Way
+else
+begin: TAG_1WAY
+ assign tag_in = tag_in0_r;
+ assign tag_out0_w = tag_out;
+ assign tag_out1_w = {(CACHE_TAG_WIDTH){1'b0}};
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Data memory
+//-----------------------------------------------------------------
+wire [31:0] way0_instruction_w /*verilator public*/;
+wire [31:0] way1_instruction_w /*verilator public*/;
+
+// Way 0 Instruction Memory
+altor32_ram_dp
+#(
+ .WIDTH(32),
+ .SIZE(CACHE_DWIDTH)
+)
+u2_data_way0
+(
+ // Data read port
+ .aclk_i(clk_i),
+ .aadr_i(address_rd_w),
+ .adat_o(way0_instruction_w),
+ .adat_i(32'h00),
+ .awr_i(1'b0),
+
+ // Data write port
+ .bclk_i(clk_i),
+ .badr_i(address_wr_w),
+ .bdat_o(/*open*/),
+ .bdat_i(mem_data_w),
+ .bwr_i(cache_wr0_w)
+);
+
+// Way 1 Instruction Memory
+altor32_ram_dp
+#(
+ .WIDTH(32),
+ .SIZE(CACHE_DWIDTH)
+)
+u2_data_way1
+(
+ // Data read port
+ .aclk_i(clk_i),
+ .aadr_i(address_rd_w),
+ .adat_o(way1_instruction_w),
+ .adat_i(32'h00),
+ .awr_i(1'b0),
+
+ // Data write port
+ .bclk_i(clk_i),
+ .badr_i(address_wr_w),
+ .bdat_o(/*open*/),
+ .bdat_i(mem_data_w),
+ .bwr_i(cache_wr1_w)
+);
+
+// Select between ways for result
+assign instruction_o = (miss0_w == 1'b0) ? way0_instruction_w : way1_instruction_w;
+
+// Write to cache on wishbone response
+assign address_wr_w = {miss_pc_q[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], mem_resp_addr_w[CACHE_LINE_SIZE_WIDTH-1:2]};
+
+assign cache_wr0_w = (state_q == STATE_FETCH) & mem_valid_w & ~way_update_q;
+assign cache_wr1_w = (state_q == STATE_FETCH) & mem_valid_w & way_update_q;
+
+endmodule
altor32/rtl/cpu/altor32_icache.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_lfu.v
===================================================================
--- altor32/rtl/cpu/altor32_lfu.v (nonexistent)
+++ altor32/rtl/cpu/altor32_lfu.v (revision 25)
@@ -0,0 +1,138 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module: Load Forwarding Unit
+//-----------------------------------------------------------------
+module altor32_lfu
+(
+ // Opcode
+ input [7:0] opcode_i /*verilator public*/,
+
+ // Memory load result
+ input [31:0] mem_result_i /*verilator public*/,
+ input [1:0] mem_offset_i /*verilator public*/,
+
+ // Result
+ output reg [31:0] load_result_o /*verilator public*/,
+ output reg load_insn_o /*verilator public*/
+);
+
+//-------------------------------------------------------------------
+// Load forwarding unit
+//-------------------------------------------------------------------
+always @ *
+begin
+ load_result_o = 32'h00000000;
+ load_insn_o = 1'b0;
+
+ case (opcode_i)
+
+ `INST_OR32_LBS: // l.lbs
+ begin
+ case (mem_offset_i)
+ 2'b00 : load_result_o[7:0] = mem_result_i[31:24];
+ 2'b01 : load_result_o[7:0] = mem_result_i[23:16];
+ 2'b10 : load_result_o[7:0] = mem_result_i[15:8];
+ 2'b11 : load_result_o[7:0] = mem_result_i[7:0];
+ default : ;
+ endcase
+
+ // Sign extend LB
+ if (load_result_o[7] == 1'b1)
+ load_result_o[31:8] = 24'hFFFFFF;
+
+ load_insn_o = 1'b1;
+ end
+
+ `INST_OR32_LBZ: // l.lbz
+ begin
+ case (mem_offset_i)
+ 2'b00 : load_result_o[7:0] = mem_result_i[31:24];
+ 2'b01 : load_result_o[7:0] = mem_result_i[23:16];
+ 2'b10 : load_result_o[7:0] = mem_result_i[15:8];
+ 2'b11 : load_result_o[7:0] = mem_result_i[7:0];
+ default : ;
+ endcase
+
+ load_insn_o = 1'b1;
+ end
+
+ `INST_OR32_LHS: // l.lhs
+ begin
+ case (mem_offset_i)
+ 2'b00 : load_result_o[15:0] = mem_result_i[31:16];
+ 2'b10 : load_result_o[15:0] = mem_result_i[15:0];
+ default : ;
+ endcase
+
+ // Sign extend LH
+ if (load_result_o[15] == 1'b1)
+ load_result_o[31:16] = 16'hFFFF;
+
+ load_insn_o = 1'b1;
+ end
+
+ `INST_OR32_LHZ: // l.lhz
+ begin
+ case (mem_offset_i)
+ 2'b00 : load_result_o[15:0] = mem_result_i[31:16];
+ 2'b10 : load_result_o[15:0] = mem_result_i[15:0];
+ default : ;
+ endcase
+
+ load_insn_o = 1'b1;
+ end
+
+ `INST_OR32_LWZ, `INST_OR32_LWS: // l.lwz l.lws
+ begin
+ load_result_o = mem_result_i;
+ load_insn_o = 1'b1;
+ end
+
+ default :
+ ;
+ endcase
+end
+
+endmodule
altor32/rtl/cpu/altor32_lfu.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_lsu.v
===================================================================
--- altor32/rtl/cpu/altor32_lsu.v (nonexistent)
+++ altor32/rtl/cpu/altor32_lsu.v (revision 25)
@@ -0,0 +1,160 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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: Load / Store Unit
+//-----------------------------------------------------------------
+module altor32_lsu
+(
+ // Current instruction
+ input opcode_valid_i /*verilator public*/,
+ input [7:0] opcode_i /*verilator public*/,
+
+ // Load / Store pending
+ input load_pending_i /*verilator public*/,
+ input store_pending_i /*verilator public*/,
+
+ // Load dest register
+ input [4:0] rd_load_i /*verilator public*/,
+
+ // Load insn in WB stage
+ input load_wb_i /*verilator public*/,
+
+ // Memory status
+ input mem_access_i /*verilator public*/,
+ input mem_ack_i /*verilator public*/,
+
+ // Load / store still pending
+ output reg load_pending_o /*verilator public*/,
+ output reg store_pending_o /*verilator public*/,
+
+ // Insert load result into pipeline
+ output reg write_result_o /*verilator public*/,
+
+ // Stall pipeline due load / store / insert
+ output reg stall_o /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+`define ADD_FUNCTION
+`include "altor32_funcs.v"
+
+//-------------------------------------------------------------------
+// Outstanding memory access logic
+//-------------------------------------------------------------------
+reg inst_load_r;
+reg inst_store_r;
+
+always @ *
+begin
+
+ load_pending_o = load_pending_i;
+ store_pending_o = store_pending_i;
+ stall_o = 1'b0;
+ write_result_o = 1'b0;
+
+ // Is this instruction a load or store?
+ inst_load_r = is_load_operation(opcode_i);
+ inst_store_r = is_store_operation(opcode_i);
+
+ // Store operation just completed?
+ if (store_pending_o & mem_ack_i & ~mem_access_i)
+ begin
+ `ifdef CONF_CORE_DEBUG
+ $display(" Store operation now completed");
+ `endif
+ store_pending_o = 1'b0;
+ end
+
+ // Load just completed (and result ready in-time for writeback stage)?
+ if (load_pending_o & mem_ack_i & ~mem_access_i & load_wb_i)
+ begin
+ // Load complete
+ load_pending_o = 1'b0;
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Load operation completed in writeback stage");
+ `endif
+ end
+ // Load just completed (later than writeback stage)?
+ else if (load_pending_o & mem_ack_i & ~mem_access_i)
+ begin
+ `ifdef CONF_CORE_DEBUG
+ $display(" Load operation completed later than writeback stage");
+ `endif
+
+ // Valid target register?
+ if (rd_load_i != 5'b00000)
+ begin
+ `ifdef CONF_CORE_DEBUG
+ $display(" Load result now ready for R%d", rd_load_i);
+ `endif
+ // Stall instruction and write load result to pipeline
+ stall_o = opcode_valid_i;
+ write_result_o = 1'b1;
+ end
+ else
+ begin
+ `ifdef CONF_CORE_DEBUG
+ $display(" Load result ready but not needed");
+ `endif
+ end
+
+ // Load complete
+ load_pending_o = 1'b0;
+ end
+
+ // If load or store in progress (and this instruction is valid)
+ if ((load_pending_o | store_pending_o) & opcode_valid_i)
+ begin
+ // Load or store whilst memory bus busy
+ if (inst_load_r | inst_store_r)
+ begin
+ `ifdef CONF_CORE_DEBUG
+ $display(" Data bus already busy, stall (load_pending_o=%d, store_pending_o=%d)", load_pending_o, store_pending_o);
+ `endif
+ // Stall!
+ stall_o = 1'b1;
+ end
+ end
+end
+
+endmodule
altor32/rtl/cpu/altor32_lsu.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_noicache.v
===================================================================
--- altor32/rtl/cpu/altor32_noicache.v (nonexistent)
+++ altor32/rtl/cpu/altor32_noicache.v (revision 25)
@@ -0,0 +1,159 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module - Cache substitute (used when ICache disabled)
+//-----------------------------------------------------------------
+module altor32_noicache
+(
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Processor interface
+ input rd_i /*verilator public*/,
+ input [31:0] pc_i /*verilator public*/,
+ output [31:0] instruction_o /*verilator public*/,
+ output valid_o /*verilator public*/,
+
+ // Invalidate (not used)
+ input invalidate_i /*verilator public*/,
+
+ // Memory interface
+ output [31:0] wbm_addr_o /*verilator public*/,
+ input [31:0] wbm_dat_i /*verilator public*/,
+ output [2:0] wbm_cti_o /*verilator public*/,
+ output wbm_cyc_o /*verilator public*/,
+ output wbm_stb_o /*verilator public*/,
+ input wbm_stall_i/*verilator public*/,
+ input wbm_ack_i/*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+// Current state
+parameter STATE_CHECK = 0;
+parameter STATE_FETCH = 1;
+reg state_q;
+
+reg drop_resp_q;
+
+wire mem_fetch_w = (state_q == STATE_CHECK);
+wire mem_valid_w;
+wire mem_final_w;
+
+//-----------------------------------------------------------------
+// Fetch unit
+//-----------------------------------------------------------------
+altor32_wb_fetch
+u_wb
+(
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+
+ .fetch_i(mem_fetch_w),
+ .burst_i(1'b0),
+ .address_i(pc_i),
+
+ .resp_addr_o(/* not used */),
+ .data_o(instruction_o),
+ .valid_o(mem_valid_w),
+ .final_o(mem_final_w),
+
+ .wbm_addr_o(wbm_addr_o),
+ .wbm_dat_i(wbm_dat_i),
+ .wbm_cti_o(wbm_cti_o),
+ .wbm_cyc_o(wbm_cyc_o),
+ .wbm_stb_o(wbm_stb_o),
+ .wbm_stall_i(wbm_stall_i),
+ .wbm_ack_i(wbm_ack_i)
+);
+
+//-----------------------------------------------------------------
+// Control logic
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ drop_resp_q <= 1'b0;
+ state_q <= STATE_CHECK;
+ end
+ else
+ begin
+ case (state_q)
+
+ //-----------------------------------------
+ // CHECK - Accept read request
+ //-----------------------------------------
+ STATE_CHECK :
+ begin
+ drop_resp_q <= 1'b0;
+ state_q <= STATE_FETCH;
+ end
+ //-----------------------------------------
+ // FETCH - Wait for read response
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Read whilst waiting for previous response?
+ if (rd_i)
+ drop_resp_q <= 1'b1;
+
+ // Data ready from memory?
+ if (mem_final_w)
+ state_q <= STATE_CHECK;
+ end
+
+ default:
+ ;
+ endcase
+ end
+end
+
+assign valid_o = mem_valid_w & ~drop_resp_q & ~rd_i;
+assign instruction_o = wbm_dat_i;
+
+endmodule
+
altor32/rtl/cpu/altor32_noicache.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_ram_dp.v
===================================================================
--- altor32/rtl/cpu/altor32_ram_dp.v (nonexistent)
+++ altor32/rtl/cpu/altor32_ram_dp.v (revision 25)
@@ -0,0 +1,106 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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: altor32_ram_dp - Dual port RAM (used in cache)
+//-----------------------------------------------------------------
+module altor32_ram_dp
+#(
+ parameter WIDTH = 8,
+ parameter SIZE = 14
+)
+(
+ input aclk_i /*verilator public*/,
+ output [(WIDTH - 1):0] adat_o /*verilator public*/,
+ input [(WIDTH - 1):0] adat_i /*verilator public*/,
+ input [(SIZE - 1):0] aadr_i /*verilator public*/,
+ input awr_i /*verilator public*/,
+
+ input bclk_i /*verilator public*/,
+ output [(WIDTH - 1):0] bdat_o /*verilator public*/,
+ input [(WIDTH - 1):0] bdat_i /*verilator public*/,
+ input [(SIZE - 1):0] badr_i /*verilator public*/,
+ input bwr_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+/* verilator lint_off MULTIDRIVEN */
+reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/;
+/* verilator lint_on MULTIDRIVEN */
+
+reg [(SIZE - 1):0] rd_addr_a_q;
+reg [(SIZE - 1):0] rd_addr_b_q;
+
+//-----------------------------------------------------------------
+// Processes
+//-----------------------------------------------------------------
+always @ (posedge aclk_i)
+begin
+ if (awr_i == 1'b1)
+ ram[aadr_i] <= adat_i;
+ rd_addr_a_q <= aadr_i;
+end
+always @ (posedge bclk_i)
+begin
+ if (bwr_i == 1'b1)
+ ram[badr_i] <= bdat_i;
+ rd_addr_b_q <= badr_i;
+end
+
+//-------------------------------------------------------------------
+// Combinatorial
+//-------------------------------------------------------------------
+assign adat_o = ram[rd_addr_a_q];
+assign bdat_o = ram[rd_addr_b_q];
+
+//-----------------------------------------------------------------
+// Init Memory
+//-----------------------------------------------------------------
+`ifdef ALTOR32_CLEAR_RAM
+ integer i;
+ initial
+ begin
+ for (i=0;i<((2<< (SIZE-1)) - 1);i=i+1)
+ begin
+ ram[i] = 0;
+ end
+ end
+`endif
+
+endmodule
altor32/rtl/cpu/altor32_ram_dp.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_ram_sp.v
===================================================================
--- altor32/rtl/cpu/altor32_ram_sp.v (nonexistent)
+++ altor32/rtl/cpu/altor32_ram_sp.v (revision 25)
@@ -0,0 +1,89 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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: altor32_ram_sp - Single port RAM (used in cache)
+//-----------------------------------------------------------------
+module altor32_ram_sp
+#(
+ parameter [31:0] WIDTH = 8,
+ parameter [31:0] SIZE = 14
+)
+(
+ input clk_i /*verilator public*/,
+ output [(WIDTH - 1):0] dat_o /*verilator public*/,
+ input [(WIDTH - 1):0] dat_i /*verilator public*/,
+ input [(SIZE - 1):0] adr_i /*verilator public*/,
+ input wr_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/;
+reg [(SIZE - 1):0] rd_addr_q;
+
+//-----------------------------------------------------------------
+// Processes
+//-----------------------------------------------------------------
+always @ (posedge clk_i)
+begin
+ if (wr_i == 1'b1)
+ ram[adr_i] <= dat_i;
+ rd_addr_q <= adr_i;
+end
+
+//-------------------------------------------------------------------
+// Combinatorial
+//-------------------------------------------------------------------
+assign dat_o = ram[rd_addr_q];
+
+//-----------------------------------------------------------------
+// Init Memory
+//-----------------------------------------------------------------
+`ifdef ALTOR32_CLEAR_RAM
+ integer i;
+ initial
+ begin
+ for (i=0;i<((2<< (SIZE-1)) - 1);i=i+1)
+ begin
+ ram[i] = 0;
+ end
+ end
+`endif
+
+endmodule
altor32/rtl/cpu/altor32_ram_sp.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_regfile_alt.v
===================================================================
--- altor32/rtl/cpu/altor32_regfile_alt.v (nonexistent)
+++ altor32/rtl/cpu/altor32_regfile_alt.v (revision 25)
@@ -0,0 +1,185 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`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] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+ input [4:0] rd_i /*verilator public*/,
+ output reg [31:0] reg_ra_o /*verilator public*/,
+ output reg [31:0] reg_rb_o /*verilator public*/,
+ input [31:0] reg_rd_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter SUPPORT_32REGS = "ENABLED";
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+wire clk_delayed_w;
+wire [31:0] reg_ra_w;
+wire [31:0] reg_rb_w;
+wire write_enable_w;
+
+reg [4:0] addr_q;
+reg [31:0] data_q;
+
+wire [31:0] ra_w;
+wire [31:0] rb_w;
+
+//-----------------------------------------------------------------
+// Sync addr & data
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i)
+ begin
+ addr_q <= 5'b00000;
+ data_q <= 32'h00000000;
+
+ end
+ else
+ begin
+ addr_q <= rd_i;
+ data_q <= 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_w),
+ .rdclken(1'b1),
+ .rdaddress(ra_i),
+ .rden(1'b1),
+ .data(reg_rd_i),
+ .wraddress(rd_i),
+ .wren(write_enable_w),
+ .wrclock(clk_i),
+ .wrclken(1'b1),
+ .q(ra_w)
+);
+
+
+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_w),
+ .rdclken(1'b1),
+ .rdaddress(rb_i),
+ .rden(1'b1),
+ .data(reg_rd_i),
+ .wraddress(rd_i),
+ .wren(write_enable_w),
+ .wrclock(clk_i),
+ .wrclken(1'b1),
+ .q(rb_w)
+);
+
+//-----------------------------------------------------------------
+// Combinatorial Assignments
+//-----------------------------------------------------------------
+
+// Delayed clock
+assign clk_delayed_w = !clk_i;
+
+// Register read ports
+always @ *
+begin
+ if (ra_i == 5'b00000)
+ reg_ra_o = 32'h00000000;
+ else
+ reg_ra_o = reg_ra_w;
+
+ if (rb_i == 5'b00000)
+ reg_rb_o = 32'h00000000;
+ else
+ reg_rb_o = reg_rb_w;
+end
+
+assign write_enable_w = (rd_i != 5'b00000) & wr_i;
+
+// Reads are bypassed during write-back
+assign reg_ra_w = (ra_i != addr_q) ? ra_w : data_q;
+assign reg_rb_w = (rb_i != addr_q) ? rb_w : data_q;
+
+endmodule
altor32/rtl/cpu/altor32_regfile_alt.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_regfile_sim.v
===================================================================
--- altor32/rtl/cpu/altor32_regfile_sim.v (nonexistent)
+++ altor32/rtl/cpu/altor32_regfile_sim.v (revision 25)
@@ -0,0 +1,442 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`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] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+ input [4:0] rd_i /*verilator public*/,
+ output reg [31:0] reg_ra_o /*verilator public*/,
+ output reg [31:0] reg_rb_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 (ra_i)
+ 5'b00000 :
+ reg_ra_o = 32'h00000000;
+ 5'b00001 :
+ reg_ra_o = reg_r1_sp;
+ 5'b00010 :
+ reg_ra_o = reg_r2_fp;
+ 5'b00011 :
+ reg_ra_o = reg_r3;
+ 5'b00100 :
+ reg_ra_o = reg_r4;
+ 5'b00101 :
+ reg_ra_o = reg_r5;
+ 5'b00110 :
+ reg_ra_o = reg_r6;
+ 5'b00111 :
+ reg_ra_o = reg_r7;
+ 5'b01000 :
+ reg_ra_o = reg_r8;
+ 5'b01001 :
+ reg_ra_o = reg_r9_lr;
+ 5'b01010 :
+ reg_ra_o = reg_r10;
+ 5'b01011 :
+ reg_ra_o = reg_r11;
+ 5'b01100 :
+ reg_ra_o = reg_r12;
+ 5'b01101 :
+ reg_ra_o = reg_r13;
+ 5'b01110 :
+ reg_ra_o = reg_r14;
+ 5'b01111 :
+ reg_ra_o = reg_r15;
+ 5'b10000 :
+ reg_ra_o = reg_r16;
+ 5'b10001 :
+ reg_ra_o = reg_r17;
+ 5'b10010 :
+ reg_ra_o = reg_r18;
+ 5'b10011 :
+ reg_ra_o = reg_r19;
+ 5'b10100 :
+ reg_ra_o = reg_r20;
+ 5'b10101 :
+ reg_ra_o = reg_r21;
+ 5'b10110 :
+ reg_ra_o = reg_r22;
+ 5'b10111 :
+ reg_ra_o = reg_r23;
+ 5'b11000 :
+ reg_ra_o = reg_r24;
+ 5'b11001 :
+ reg_ra_o = reg_r25;
+ 5'b11010 :
+ reg_ra_o = reg_r26;
+ 5'b11011 :
+ reg_ra_o = reg_r27;
+ 5'b11100 :
+ reg_ra_o = reg_r28;
+ 5'b11101 :
+ reg_ra_o = reg_r29;
+ 5'b11110 :
+ reg_ra_o = reg_r30;
+ 5'b11111 :
+ reg_ra_o = reg_r31;
+ default :
+ reg_ra_o = 32'h00000000;
+ endcase
+
+ case (rb_i)
+ 5'b00000 :
+ reg_rb_o = 32'h00000000;
+ 5'b00001 :
+ reg_rb_o = reg_r1_sp;
+ 5'b00010 :
+ reg_rb_o = reg_r2_fp;
+ 5'b00011 :
+ reg_rb_o = reg_r3;
+ 5'b00100 :
+ reg_rb_o = reg_r4;
+ 5'b00101 :
+ reg_rb_o = reg_r5;
+ 5'b00110 :
+ reg_rb_o = reg_r6;
+ 5'b00111 :
+ reg_rb_o = reg_r7;
+ 5'b01000 :
+ reg_rb_o = reg_r8;
+ 5'b01001 :
+ reg_rb_o = reg_r9_lr;
+ 5'b01010 :
+ reg_rb_o = reg_r10;
+ 5'b01011 :
+ reg_rb_o = reg_r11;
+ 5'b01100 :
+ reg_rb_o = reg_r12;
+ 5'b01101 :
+ reg_rb_o = reg_r13;
+ 5'b01110 :
+ reg_rb_o = reg_r14;
+ 5'b01111 :
+ reg_rb_o = reg_r15;
+ 5'b10000 :
+ reg_rb_o = reg_r16;
+ 5'b10001 :
+ reg_rb_o = reg_r17;
+ 5'b10010 :
+ reg_rb_o = reg_r18;
+ 5'b10011 :
+ reg_rb_o = reg_r19;
+ 5'b10100 :
+ reg_rb_o = reg_r20;
+ 5'b10101 :
+ reg_rb_o = reg_r21;
+ 5'b10110 :
+ reg_rb_o = reg_r22;
+ 5'b10111 :
+ reg_rb_o = reg_r23;
+ 5'b11000 :
+ reg_rb_o = reg_r24;
+ 5'b11001 :
+ reg_rb_o = reg_r25;
+ 5'b11010 :
+ reg_rb_o = reg_r26;
+ 5'b11011 :
+ reg_rb_o = reg_r27;
+ 5'b11100 :
+ reg_rb_o = reg_r28;
+ 5'b11101 :
+ reg_rb_o = reg_r29;
+ 5'b11110 :
+ reg_rb_o = reg_r30;
+ 5'b11111 :
+ reg_rb_o = reg_r31;
+ default :
+ reg_rb_o = 32'h00000000;
+ endcase
+ end
+end
+else
+begin
+ // Asynchronous Register read (Rs & Rd)
+ always @ *
+ begin
+ case (ra_i)
+ 5'b00000 :
+ reg_ra_o = 32'h00000000;
+ 5'b00001 :
+ reg_ra_o = reg_r1_sp;
+ 5'b00010 :
+ reg_ra_o = reg_r2_fp;
+ 5'b00011 :
+ reg_ra_o = reg_r3;
+ 5'b00100 :
+ reg_ra_o = reg_r4;
+ 5'b00101 :
+ reg_ra_o = reg_r5;
+ 5'b00110 :
+ reg_ra_o = reg_r6;
+ 5'b00111 :
+ reg_ra_o = reg_r7;
+ 5'b01000 :
+ reg_ra_o = reg_r8;
+ 5'b01001 :
+ reg_ra_o = reg_r9_lr;
+ 5'b01010 :
+ reg_ra_o = reg_r10;
+ 5'b01011 :
+ reg_ra_o = reg_r11;
+ 5'b01100 :
+ reg_ra_o = reg_r12;
+ 5'b01101 :
+ reg_ra_o = reg_r13;
+ 5'b01110 :
+ reg_ra_o = reg_r14;
+ 5'b01111 :
+ reg_ra_o = reg_r15;
+ default :
+ reg_ra_o = 32'h00000000;
+ endcase
+
+ case (rb_i)
+ 5'b00000 :
+ reg_rb_o = 32'h00000000;
+ 5'b00001 :
+ reg_rb_o = reg_r1_sp;
+ 5'b00010 :
+ reg_rb_o = reg_r2_fp;
+ 5'b00011 :
+ reg_rb_o = reg_r3;
+ 5'b00100 :
+ reg_rb_o = reg_r4;
+ 5'b00101 :
+ reg_rb_o = reg_r5;
+ 5'b00110 :
+ reg_rb_o = reg_r6;
+ 5'b00111 :
+ reg_rb_o = reg_r7;
+ 5'b01000 :
+ reg_rb_o = reg_r8;
+ 5'b01001 :
+ reg_rb_o = reg_r9_lr;
+ 5'b01010 :
+ reg_rb_o = reg_r10;
+ 5'b01011 :
+ reg_rb_o = reg_r11;
+ 5'b01100 :
+ reg_rb_o = reg_r12;
+ 5'b01101 :
+ reg_rb_o = reg_r13;
+ 5'b01110 :
+ reg_rb_o = reg_r14;
+ 5'b01111 :
+ reg_rb_o = reg_r15;
+ default :
+ reg_rb_o = 32'h00000000;
+ endcase
+ end
+end
+endgenerate
+
+endmodule
altor32/rtl/cpu/altor32_regfile_sim.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_regfile_xil.v
===================================================================
--- altor32/rtl/cpu/altor32_regfile_xil.v (nonexistent)
+++ altor32/rtl/cpu/altor32_regfile_xil.v (revision 25)
@@ -0,0 +1,137 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`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] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+ input [4:0] rd_i /*verilator public*/,
+ output reg [31:0] reg_ra_o /*verilator public*/,
+ output reg [31:0] reg_rb_o /*verilator public*/,
+ input [31:0] reg_rd_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter SUPPORT_32REGS = "ENABLED";
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+wire [31:0] reg_ra_w;
+wire [31:0] reg_rb_w;
+wire [31:0] ra_0_15_w;
+wire [31:0] ra_16_31_w;
+wire [31:0] rb_0_15_w;
+wire [31:0] rb_16_31_w;
+wire write_enable_w;
+wire write_banka_w;
+wire write_bankb_w;
+
+//-----------------------------------------------------------------
+// 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(write_banka_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(ra_0_15_w[i]), .SPO(/* open */));
+ RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(write_banka_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rb_0_15_w[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_bit1b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(ra_16_31_w[i]), .SPO(/* open */));
+ RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rb_16_31_w[i]), .SPO(/* open */));
+ end
+end
+else
+begin
+ assign ra_16_31_w = 32'h00000000;
+ assign rb_16_31_w = 32'h00000000;
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Combinatorial Assignments
+//-----------------------------------------------------------------
+assign reg_ra_w = (ra_i[4] == 1'b0) ? ra_0_15_w : ra_16_31_w;
+assign reg_rb_w = (rb_i[4] == 1'b0) ? rb_0_15_w : rb_16_31_w;
+
+assign write_enable_w = (rd_i != 5'b00000) & wr_i;
+
+assign write_banka_w = (write_enable_w & (~rd_i[4]));
+assign write_bankb_w = (write_enable_w & rd_i[4]);
+
+// Register read ports
+always @ *
+begin
+ if (ra_i == 5'b00000)
+ reg_ra_o = 32'h00000000;
+ else
+ reg_ra_o = reg_ra_w;
+
+ if (rb_i == 5'b00000)
+ reg_rb_o = 32'h00000000;
+ else
+ reg_rb_o = reg_rb_w;
+end
+
+endmodule
altor32/rtl/cpu/altor32_regfile_xil.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_wb_fetch.v
===================================================================
--- altor32/rtl/cpu/altor32_wb_fetch.v (nonexistent)
+++ altor32/rtl/cpu/altor32_wb_fetch.v (revision 25)
@@ -0,0 +1,179 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module - Wishbone fetch unit
+//-----------------------------------------------------------------
+module altor32_wb_fetch
+(
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Fetch
+ input fetch_i /*verilator public*/,
+ input burst_i /*verilator public*/,
+ input [31:0] address_i /*verilator public*/,
+
+ // Response
+ output [31:0] resp_addr_o /*verilator public*/,
+ output [31:0] data_o /*verilator public*/,
+ output valid_o /*verilator public*/,
+ output final_o /*verilator public*/,
+
+ // Memory interface
+ output reg [31:0] wbm_addr_o /*verilator public*/,
+ input [31:0] wbm_dat_i /*verilator public*/,
+ output reg [2:0] wbm_cti_o /*verilator public*/,
+ output reg wbm_cyc_o /*verilator public*/,
+ output reg wbm_stb_o /*verilator public*/,
+ input wbm_stall_i/*verilator public*/,
+ input wbm_ack_i/*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter FETCH_WORDS_W = 3; /* 2 ^ 3 * 4 = 32 */
+parameter FETCH_BYTES_W = FETCH_WORDS_W + 2;
+
+parameter WB_CTI_BURST = 3'b010;
+parameter WB_CTI_FINAL = 3'b111;
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+// Word currently being fetched within a line
+reg [FETCH_WORDS_W-1:0] fetch_word_q;
+reg [FETCH_WORDS_W-1:0] resp_word_q;
+
+wire [FETCH_WORDS_W-1:0] next_word_w = fetch_word_q + 1;
+
+wire penultimate_word_w = (fetch_word_q == ({FETCH_WORDS_W{1'b1}}-1));
+
+wire final_resp_w = ((resp_word_q == {FETCH_WORDS_W{1'b1}}) | ~burst_i);
+
+//-----------------------------------------------------------------
+// Pipelined Wishbone Master
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ wbm_addr_o <= 32'h00000000;
+ wbm_cti_o <= 3'b0;
+ wbm_stb_o <= 1'b0;
+ wbm_cyc_o <= 1'b0;
+
+ fetch_word_q <= {FETCH_WORDS_W{1'b0}};
+ resp_word_q <= {FETCH_WORDS_W{1'b0}};
+ end
+ else
+ begin
+ // Idle
+ if (!wbm_cyc_o)
+ begin
+ if (fetch_i)
+ begin
+ if (burst_i)
+ begin
+ wbm_addr_o <= {address_i[31:FETCH_BYTES_W], {FETCH_BYTES_W{1'b0}}};
+ fetch_word_q <= {FETCH_WORDS_W{1'b0}};
+ resp_word_q <= {FETCH_WORDS_W{1'b0}};
+
+ // Incrementing linear burst
+ wbm_cti_o <= WB_CTI_BURST;
+ end
+ else
+ begin
+ wbm_addr_o <= address_i;
+ resp_word_q <= address_i[FETCH_BYTES_W-1:2];
+
+ // Single fetch
+ wbm_cti_o <= WB_CTI_FINAL;
+ end
+
+ // Start fetch from memory
+ wbm_stb_o <= 1'b1;
+ wbm_cyc_o <= 1'b1;
+ end
+ end
+ // Access in-progress
+ else
+ begin
+ // Command accepted
+ if (~wbm_stall_i)
+ begin
+ // Fetch next word for line
+ if (wbm_cti_o != WB_CTI_FINAL)
+ begin
+ wbm_addr_o <= {wbm_addr_o[31:FETCH_BYTES_W], next_word_w, 2'b0};
+ fetch_word_q <= next_word_w;
+
+ // Final word to read?
+ if (penultimate_word_w)
+ wbm_cti_o <= WB_CTI_FINAL;
+ end
+ // Fetch complete
+ else
+ wbm_stb_o <= 1'b0;
+ end
+
+ // Response
+ if (wbm_ack_i)
+ resp_word_q <= resp_word_q + 1;
+
+ // Last response?
+ if (final_o)
+ wbm_cyc_o <= 1'b0;
+ end
+ end
+end
+
+// Response
+assign data_o = wbm_dat_i;
+assign valid_o = wbm_ack_i;
+assign final_o = final_resp_w & wbm_ack_i;
+assign resp_addr_o = {address_i[31:FETCH_BYTES_W], resp_word_q, 2'b0};
+
+endmodule
altor32/rtl/cpu/altor32_wb_fetch.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu/altor32_writeback.v
===================================================================
--- altor32/rtl/cpu/altor32_writeback.v (nonexistent)
+++ altor32/rtl/cpu/altor32_writeback.v (revision 25)
@@ -0,0 +1,164 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+//-----------------------------------------------------------------
+`define ADD_DEF
+`include "altor32_defs.v"
+
+//-----------------------------------------------------------------
+// Module - Writeback
+//-----------------------------------------------------------------
+module altor32_writeback
+(
+ // General
+ input clk_i /*verilator public*/,
+ input rst_i /*verilator public*/,
+
+ // Opcode
+ input [31:0] opcode_i /*verilator public*/,
+
+ // Register target
+ input [4:0] rd_i /*verilator public*/,
+
+ // ALU result
+ input [31:0] alu_result_i /*verilator public*/,
+
+ // Memory load result
+ input [31:0] mem_result_i /*verilator public*/,
+ input [1:0] mem_offset_i /*verilator public*/,
+ input mem_ready_i /*verilator public*/,
+
+ // Multiplier result
+ input [63:0] mult_result_i /*verilator public*/,
+
+ // Outputs
+ output reg write_enable_o /*verilator public*/,
+ output reg [4:0] write_addr_o /*verilator public*/,
+ output reg [31:0] write_data_o /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+// Register address
+reg [4:0] rd_q;
+
+// Register writeback value
+reg [31:0] result_q;
+
+reg [7:0] opcode_q;
+
+// Register writeback enable
+reg write_rd_q;
+
+reg [1:0] mem_offset_q;
+
+//-------------------------------------------------------------------
+// Pipeline Registers
+//-------------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ write_rd_q <= 1'b1;
+ result_q <= 32'h00000000;
+ rd_q <= 5'b00000;
+ opcode_q <= 8'b0;
+ mem_offset_q <= 2'b0;
+ end
+ else
+ begin
+ rd_q <= rd_i;
+ result_q <= alu_result_i;
+
+ opcode_q <= {2'b00,opcode_i[31:26]};
+ mem_offset_q<= mem_offset_i;
+
+ // Register writeback required?
+ if (rd_i != 5'b00000)
+ write_rd_q <= 1'b1;
+ else
+ write_rd_q <= 1'b0;
+ end
+end
+
+//-------------------------------------------------------------------
+// Load result resolve
+//-------------------------------------------------------------------
+wire load_inst_w;
+wire [31:0] load_result_w;
+
+altor32_lfu
+u_lfu
+(
+ // Opcode
+ .opcode_i(opcode_q),
+
+ // Memory load result
+ .mem_result_i(mem_result_i),
+ .mem_offset_i(mem_offset_q),
+
+ // Result
+ .load_result_o(load_result_w),
+ .load_insn_o(load_inst_w)
+);
+
+//-------------------------------------------------------------------
+// Writeback
+//-------------------------------------------------------------------
+always @ *
+begin
+ write_addr_o = rd_q;
+
+ // Load result
+ if (load_inst_w)
+ begin
+ write_enable_o = write_rd_q & mem_ready_i;
+ write_data_o = load_result_w;
+ end
+ // Normal ALU instruction
+ else
+ begin
+ write_enable_o = write_rd_q;
+ write_data_o = result_q;
+ end
+end
+
+endmodule
altor32/rtl/cpu/altor32_writeback.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32.v
===================================================================
--- altor32/rtl/cpu_lite/altor32.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32.v (revision 25)
@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
altor32/rtl/cpu_lite/altor32.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_alu.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_alu.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_alu.v (revision 25)
@@ -0,0 +1,244 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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 - 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*/,
+
+ // Comparison
+ output reg equal_o /*verilator public*/,
+ output reg greater_than_signed_o /*verilator public*/,
+ output reg greater_than_o /*verilator public*/,
+ output reg less_than_signed_o /*verilator public*/,
+ output reg less_than_o /*verilator public*/,
+ output flag_update_o /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------
+`include "altor32_defs.v"
+`include "altor32_funcs.v"
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+reg [31:0] result_r;
+
+reg [31:16] shift_right_fill_r;
+reg [31:0] shift_right_1_r;
+reg [31:0] shift_right_2_r;
+reg [31:0] shift_right_4_r;
+reg [31:0] shift_right_8_r;
+
+reg [31:0] shift_left_1_r;
+reg [31:0] shift_left_2_r;
+reg [31:0] shift_left_4_r;
+reg [31:0] shift_left_8_r;
+
+//-----------------------------------------------------------------
+// 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_r = {a_i[30:0],1'b0};
+ else
+ shift_left_1_r = a_i;
+
+ if (b_i[1] == 1'b1)
+ shift_left_2_r = {shift_left_1_r[29:0],2'b00};
+ else
+ shift_left_2_r = shift_left_1_r;
+
+ if (b_i[2] == 1'b1)
+ shift_left_4_r = {shift_left_2_r[27:0],4'b0000};
+ else
+ shift_left_4_r = shift_left_2_r;
+
+ if (b_i[3] == 1'b1)
+ shift_left_8_r = {shift_left_4_r[23:0],8'b00000000};
+ else
+ shift_left_8_r = shift_left_4_r;
+
+ if (b_i[4] == 1'b1)
+ result_r = {shift_left_8_r[15:0],16'b0000000000000000};
+ else
+ result_r = shift_left_8_r;
+
+ 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_r = 16'b1111111111111111;
+ else
+ shift_right_fill_r = 16'b0000000000000000;
+
+ if (b_i[0] == 1'b1)
+ shift_right_1_r = {shift_right_fill_r[31], a_i[31:1]};
+ else
+ shift_right_1_r = a_i;
+
+ if (b_i[1] == 1'b1)
+ shift_right_2_r = {shift_right_fill_r[31:30], shift_right_1_r[31:2]};
+ else
+ shift_right_2_r = shift_right_1_r;
+
+ if (b_i[2] == 1'b1)
+ shift_right_4_r = {shift_right_fill_r[31:28], shift_right_2_r[31:4]};
+ else
+ shift_right_4_r = shift_right_2_r;
+
+ if (b_i[3] == 1'b1)
+ shift_right_8_r = {shift_right_fill_r[31:24], shift_right_4_r[31:8]};
+ else
+ shift_right_8_r = shift_right_4_r;
+
+ if (b_i[4] == 1'b1)
+ result_r = {shift_right_fill_r[31:16], shift_right_8_r[31:16]};
+ else
+ result_r = shift_right_8_r;
+
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ //----------------------------------------------
+ // Arithmetic
+ //----------------------------------------------
+ `ALU_ADD :
+ begin
+ {c_o, result_r} = (a_i + b_i);
+ c_update_o = 1'b1;
+ end
+ `ALU_ADDC :
+ begin
+ {c_o, result_r} = (a_i + b_i) + {31'h00000000, c_i};
+ c_update_o = 1'b1;
+ end
+ `ALU_SUB :
+ begin
+ result_r = (a_i - b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ //----------------------------------------------
+ // Logical
+ //----------------------------------------------
+ `ALU_AND :
+ begin
+ result_r = (a_i & b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ `ALU_OR :
+ begin
+ result_r = (a_i | b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ `ALU_XOR :
+ begin
+ result_r = (a_i ^ b_i);
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ default :
+ begin
+ result_r = a_i;
+ c_o = 1'b0;
+ c_update_o = 1'b0;
+ end
+ endcase
+end
+
+assign p_o = result_r;
+
+//-----------------------------------------------------------------
+// Comparisons
+//-----------------------------------------------------------------
+always @ *
+begin
+ if (a_i == b_i)
+ equal_o = 1'b1;
+ else
+ equal_o = 1'b0;
+
+ if (a_i < b_i)
+ less_than_o = 1'b1;
+ else
+ less_than_o = 1'b0;
+
+ if (a_i > b_i)
+ greater_than_o = 1'b1;
+ else
+ greater_than_o = 1'b0;
+
+ less_than_signed_o = less_than_signed(a_i, b_i);
+ greater_than_signed_o = ~(less_than_signed_o | equal_o);
+end
+
+assign flag_update_o = (op_i == `ALU_COMPARE);
+
+endmodule
altor32/rtl/cpu_lite/altor32_alu.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_defs.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_defs.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_defs.v (revision 25)
@@ -0,0 +1,178 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
+`define ALU_COMPARE 4'b1010
+
+//-----------------------------------------------------------------
+// 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_SFMASK 16'hFD3F
+`define INST_OR32_SFEQ 16'h0520
+`define INST_OR32_SFGES 16'h052B
+`define INST_OR32_SFGEU 16'h0523
+`define INST_OR32_SFGTS 16'h052A
+`define INST_OR32_SFGTU 16'h0522
+`define INST_OR32_SFLES 16'h052D
+`define INST_OR32_SFLEU 16'h0525
+`define INST_OR32_SFLTS 16'h052C
+`define INST_OR32_SFLTU 16'h0524
+`define INST_OR32_SFNE 16'h0521
+
+//-----------------------------------------------------------------
+// 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 SR_SM 0
+`define SR_TEE 1
+`define SR_IEE 2
+`define SR_DCE 3
+`define SR_ICE 4
+`define SR_DME 5
+`define SR_IME 6
+`define SR_LEE 7
+`define SR_CE 8
+`define SR_F 9
+`define SR_CY 10
+`define SR_OV 11
+`define SR_OVE 12
+`define SR_DSX 13
+`define SR_EPH 14
+`define SR_FO 15
+`define SR_SUMRA 16
+`define SR_ICACHE_FLUSH 17
+`define 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
altor32/rtl/cpu_lite/altor32_defs.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_funcs.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_funcs.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_funcs.v (revision 25)
@@ -0,0 +1,253 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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
altor32/rtl/cpu_lite/altor32_funcs.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_lite.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_lite.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_lite.v (revision 25)
@@ -0,0 +1,1501 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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] pc_q;
+
+// Exception saved program counter
+reg [31:0] epc_q;
+
+// Supervisor register
+reg [31:0] sr_q;
+
+// Exception saved supervisor register
+reg [31:0] esr_q;
+
+// Destination register number (post execute stage)
+reg [4:0] ex_rd_q;
+
+// ALU input A
+reg [31:0] ex_alu_a_q;
+
+// ALU input B
+reg [31:0] ex_alu_b_q;
+
+// ALU output
+wire [31:0] ex_result_w;
+
+// ALU Carry
+wire alu_carry_out_w;
+wire alu_carry_update_w;
+
+// ALU Comparisons
+wire compare_equal_w;
+wire compare_gts_w;
+wire compare_gt_w;
+wire compare_lts_w;
+wire compare_lt_w;
+wire alu_flag_update_w;
+
+// ALU operation selection
+reg [3:0] ex_alu_func_q;
+
+// Delayed NMI
+reg nmi_q;
+
+// SIM PUTC
+`ifdef SIM_EXT_PUTC
+ reg [7:0] putc_q;
+`endif
+
+wire [4:0] ra_w;
+wire [4:0] rb_w;
+wire [4:0] rd_w;
+
+wire [31:0] reg_ra_w;
+wire [31:0] reg_rb_w;
+
+reg [31:0] opcode_q;
+
+reg [31:0] load_result_r;
+
+reg [1:0] mem_offset_q;
+
+// 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_q;
+
+//-----------------------------------------------------------------
+// Instantiation
+//-----------------------------------------------------------------
+
+// ALU
+altor32_alu alu
+(
+ // ALU operation select
+ .op_i(ex_alu_func_q),
+
+ // Operands
+ .a_i(ex_alu_a_q),
+ .b_i(ex_alu_b_q),
+ .c_i(sr_q[`SR_CY]),
+
+ // Result
+ .p_o(ex_result_w),
+
+ // Carry
+ .c_o(alu_carry_out_w),
+ .c_update_o(alu_carry_update_w),
+
+ // Comparisons
+ .equal_o(compare_equal_w),
+ .greater_than_signed_o(compare_gts_w),
+ .greater_than_o(compare_gt_w),
+ .less_than_signed_o(compare_lts_w),
+ .less_than_o(compare_lt_w),
+ .flag_update_o(alu_flag_update_w)
+);
+
+// Writeback result
+wire [31:0] w_write_res = (state_q == STATE_MEM) ? load_result_r : ex_result_w;
+
+// Writeback enable
+wire w_write_en = (state_q == STATE_MEM & mem_ack_i) | (state_q == STATE_WRITE_BACK);
+
+//-----------------------------------------------------------------
+// [Xilinx] 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
+ .ra_i(ra_w),
+ .rb_i(rb_w),
+ .rd_i(ex_rd_q),
+ .reg_ra_o(reg_ra_w),
+ .reg_rb_o(reg_rb_w),
+ .reg_rd_i(w_write_res)
+ );
+end
+//-----------------------------------------------------------------
+// [Altera] Register file
+//-----------------------------------------------------------------
+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
+ .ra_i(ra_w),
+ .rb_i(rb_w),
+ .rd_i(ex_rd_q),
+ .reg_ra_o(reg_ra_w),
+ .reg_rb_o(reg_rb_w),
+ .reg_rd_i(w_write_res)
+ );
+end
+//-----------------------------------------------------------------
+// [Simulation] Register file
+//-----------------------------------------------------------------
+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
+ .ra_i(ra_w),
+ .rb_i(rb_w),
+ .rd_i(ex_rd_q),
+ .reg_ra_o(reg_ra_w),
+ .reg_rb_o(reg_rb_w),
+ .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,opcode_q[31:26]};
+
+ // Sub instructions
+ alu_op_r = {opcode_q[9:6],opcode_q[3:0]};
+ sfxx_op_r = {5'b00,opcode_q[31:21]} & `INST_OR32_SFMASK;
+ shift_op_r = opcode_q[7:6];
+
+ // Branch target
+ target_int26_r = sign_extend_imm26(opcode_q[25:0]);
+
+ // Store immediate
+ store_int32_r = sign_extend_imm16({opcode_q[25:21],opcode_q[10:0]});
+
+ // Signed & unsigned imm -> 32-bits
+ uint16_r = opcode_q[15:0];
+ int32_r = sign_extend_imm16(opcode_q[15:0]);
+ uint32_r = extend_imm16(opcode_q[15:0]);
+
+ // Register values [ra/rb]
+ reg_ra_r = reg_ra_w;
+ reg_rb_r = reg_rb_w;
+
+ // Shift ammount (from register[rb])
+ shift_rb_r = {26'b00,reg_rb_w[5:0]};
+
+ // Shift ammount (from immediate)
+ shift_imm_r = {26'b00,opcode_q[5:0]};
+
+ // MTSPR/MFSPR operand
+ mxspr_uint16_r = (reg_ra_w[15:0] | {5'b00000,opcode_q[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_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
+wire inst_sfges_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
+
+wire inst_sfgeu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
+wire inst_sfgts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
+wire inst_sfgtu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
+wire inst_sfles_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
+wire inst_sfleu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
+wire inst_sflts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
+wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
+wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
+
+wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_SYS); // l.sys
+wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_q[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_q;
+
+ case (state_q)
+ //-----------------------------------------
+ // 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_q <= STATE_IDLE;
+ else
+ state_q <= 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;
+
+ opcode_q <= 32'h00000000;
+ mem_offset_q <= 2'b0;
+ end
+ else
+ begin
+
+ if (~mem_stall_i)
+ mem_stb_o <= 1'b0;
+
+ case (state_q)
+
+ //-----------------------------------------
+ // FETCH - Issue instruction fetch
+ //-----------------------------------------
+ STATE_FETCH :
+ begin
+ // Start fetch from memory
+ mem_addr_o <= pc_q;
+ 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
+ opcode_q <= 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", pc_q, opcode_q);
+ $display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);
+ $display(" rB[%d] = 0x%08x", rb_w, 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_q <= 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, rd_w);
+ `endif
+ end
+
+ inst_sb_w: // l.sb
+ begin
+ mem_addr_o <= {mem_addr_r[31:2], 2'b0};
+ mem_offset_q <= 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_q <= 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_q <= 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", rb_w, {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, opcode_q[31:26]};
+ wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP);
+ assign ra_w = v_is_nop ? 5'd3 : opcode_q[20:16];
+`else
+ assign ra_w = opcode_q[20:16];
+`endif
+
+assign rb_w = opcode_q[15:11];
+assign rd_w = opcode_q[25:21];
+
+//-----------------------------------------------------------------
+// Next PC
+//-----------------------------------------------------------------
+reg [31:0] next_pc_r;
+
+always @ *
+begin
+ // Next expected PC (current PC + 4)
+ next_pc_r = (pc_q + 4);
+end
+
+//-----------------------------------------------------------------
+// Next SR
+//-----------------------------------------------------------------
+reg [31:0] next_sr_r;
+reg compare_result_r;
+always @ *
+begin
+ next_sr_r = sr_q;
+
+ // Update SR.F
+ if (alu_flag_update_w)
+ next_sr_r[`SR_F] = compare_result_r;
+
+ // Latch carry if updated
+ if (alu_carry_update_w)
+ next_sr_r[`SR_CY] = alu_carry_out_w;
+
+ case (1'b1)
+ inst_mtspr_w:
+ begin
+ case (mxspr_uint16_r)
+ // SR - Supervision register
+ `SPR_REG_SR:
+ begin
+ next_sr_r[`SR_F] = reg_rb_r[`SR_F];
+ next_sr_r[`SR_CY] = reg_rb_r[`SR_CY];
+ next_sr_r[`SR_IEE] = reg_rb_r[`SR_IEE];
+ end
+ default:
+ ;
+ endcase
+ end
+ inst_rfe_w:
+ begin
+ next_sr_r[`SR_F] = esr_q[`SR_F];
+ next_sr_r[`SR_CY] = esr_q[`SR_CY];
+ next_sr_r[`SR_IEE] = esr_q[`SR_IEE];
+ end
+ inst_sfxx_w,
+ inst_sfxxi_w:
+ next_sr_r[`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 = epc_q;
+ next_esr_r = esr_q;
+
+ 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[`SR_F] = next_sr_r[`SR_F];
+ alu_input_a_r[`SR_CY] = next_sr_r[`SR_CY];
+ alu_input_a_r[`SR_IEE] = next_sr_r[`SR_IEE];
+ write_rd_r = 1'b1;
+ end
+
+ // EPCR - EPC Exception saved PC
+ `SPR_REG_EPCR:
+ begin
+ alu_input_a_r = epc_q;
+ write_rd_r = 1'b1;
+ end
+
+ // ESR - Exception saved SR
+ `SPR_REG_ESR:
+ begin
+ alu_input_a_r = 32'b0;
+ alu_input_a_r[`SR_F] = esr_q[`SR_F];
+ alu_input_a_r[`SR_CY] = esr_q[`SR_CY];
+ alu_input_a_r[`SR_IEE] = esr_q[`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.sf*i
+ inst_sfxxi_w:
+ begin
+ alu_func_r = `ALU_COMPARE;
+ alu_input_a_r = reg_ra_r;
+ alu_input_b_r = int32_r;
+ end
+
+ // l.sf*
+ inst_sfxx_w:
+ begin
+ alu_func_r = `ALU_COMPARE;
+ alu_input_a_r = reg_ra_r;
+ alu_input_b_r = reg_rb_r;
+ 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
+//-----------------------------------------------------------------
+always @ *
+begin
+ case (1'b1)
+ inst_sfges_w: // l.sfges
+ compare_result_r = compare_gts_w | compare_equal_w;
+
+ inst_sfgeu_w: // l.sfgeu
+ compare_result_r = compare_gt_w | compare_equal_w;
+
+ inst_sfgts_w: // l.sfgts
+ compare_result_r = compare_gts_w;
+
+ inst_sfgtu_w: // l.sfgtu
+ compare_result_r = compare_gt_w;
+
+ inst_sfles_w: // l.sfles
+ compare_result_r = compare_lts_w | compare_equal_w;
+
+ inst_sfleu_w: // l.sfleu
+ compare_result_r = compare_lt_w | compare_equal_w;
+
+ inst_sflts_w: // l.sflts
+ compare_result_r = compare_lts_w;
+
+ inst_sfltu_w: // l.sfltu
+ compare_result_r = compare_lt_w;
+
+ inst_sfne_w: // l.sfne
+ compare_result_r = ~compare_equal_w;
+
+ default: // l.sfeq
+ compare_result_r = compare_equal_w;
+ 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 = (pc_q + {target_int26_r[29:0],2'b00});
+
+ case (1'b1)
+ inst_bf_w: // l.bf
+ branch_r = sr_q[`SR_F];
+
+ inst_bnf_w: // l.bnf
+ branch_r = ~sr_q[`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 = epc_q;
+ 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_sfges_w,
+ inst_sfgeu_w,
+ inst_sfgts_w,
+ inst_sfgtu_w,
+ inst_sfles_w,
+ inst_sfleu_w,
+ inst_sflts_w,
+ inst_sfltu_w,
+ inst_sfne_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
+ ex_alu_func_q <= `ALU_NONE;
+ ex_alu_a_q <= 32'h00000000;
+ ex_alu_b_q <= 32'h00000000;
+ ex_rd_q <= 5'b00000;
+ end
+ else
+ begin
+ // Update ALU input flops
+ ex_alu_func_q <= alu_func_r;
+ ex_alu_a_q <= alu_input_a_r;
+ ex_alu_b_q <= alu_input_b_r;
+
+ // Branch and link (Rd = LR/R9)
+ if (branch_link_r)
+ ex_rd_q <= 5'd9;
+ // Instruction with register writeback
+ else if (write_rd_r)
+ ex_rd_q <= rd_w;
+ else
+ ex_rd_q <= 5'b0;
+ end
+end
+
+//-----------------------------------------------------------------
+// Execute: Branch / exceptions
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i == 1'b1)
+ begin
+ pc_q <= BOOT_VECTOR + `VECTOR_RESET;
+
+ // Status registers
+ epc_q <= 32'h00000000;
+ sr_q <= 32'h00000000;
+ esr_q <= 32'h00000000;
+
+ fault_o <= 1'b0;
+
+ nmi_q <= 1'b0;
+ end
+ else
+ begin
+ // Record NMI in-case it can't be processed this cycle
+ if (nmi_i)
+ nmi_q <= 1'b1;
+
+ // Core disabled?
+ if (~enable_i)
+ begin
+ // Reset
+ pc_q <= BOOT_VECTOR + `VECTOR_RESET;
+
+ // Status registers
+ epc_q <= 32'h00000000;
+ sr_q <= 32'h00000000;
+ esr_q <= 32'h00000000;
+
+ fault_o <= 1'b0;
+
+ nmi_q <= 1'b0;
+ end
+ // Write-back?
+ else if (w_write_en)
+ begin
+ // Update SR
+ sr_q <= next_sr_r;
+
+ // Exception: Instruction opcode not valid / supported, invalid PC
+ if (invalid_inst_r || (pc_q[1:0] != 2'b00))
+ begin
+ // Save PC of next instruction
+ epc_q <= next_pc_r;
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts
+ sr_q <= 32'b0;
+
+ // Set PC to exception vector
+ if (invalid_inst_r)
+ pc_q <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
+ else
+ pc_q <= ISR_VECTOR + `VECTOR_BUS_ERROR;
+
+ fault_o <= 1'b1;
+ end
+ // Exception: Syscall / Break
+ else if (branch_except_r)
+ begin
+ // Save PC of next instruction
+ epc_q <= next_pc_r;
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts
+ sr_q <= 32'b0;
+
+ // Set PC to exception vector
+ pc_q <= branch_target_r;
+
+ `ifdef CONF_CORE_DEBUG
+ $display(" Exception 0x%08x", branch_target_r);
+ `endif
+ end
+ // Non-maskable interrupt
+ else if (nmi_i | nmi_q)
+ begin
+ nmi_q <= 1'b0;
+
+ // Save PC of next instruction
+ if (branch_r)
+ epc_q <= branch_target_r;
+ // Next expected PC (current PC + 4)
+ else
+ epc_q <= next_pc_r;
+
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts
+ sr_q <= 32'b0;
+
+ // Set PC to exception vector
+ pc_q <= 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[`SR_IEE])
+ begin
+ // Save PC of next instruction & SR
+ if (branch_r)
+ epc_q <= branch_target_r;
+ // Next expected PC (current PC + 4)
+ else
+ epc_q <= next_pc_r;
+
+ esr_q <= next_sr_r;
+
+ // Disable further interrupts
+ sr_q <= 32'b0;
+
+ // Set PC to external interrupt vector
+ pc_q <= 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
+ pc_q <= 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
+ pc_q <= next_pc_r;
+ epc_q <= next_epc_r;
+ esr_q <= next_esr_r;
+ end
+ end
+ end
+end
+
+//-------------------------------------------------------------------
+// Load result
+//-------------------------------------------------------------------
+always @ *
+begin
+ load_result_r = 32'h00000000;
+
+ case (1'b1)
+
+ inst_lbs_w, // l.lbs
+ inst_lbz_w: // l.lbz
+ begin
+ case (mem_offset_q)
+ 2'b00 : load_result_r[7:0] = mem_dat_i[31:24];
+ 2'b01 : load_result_r[7:0] = mem_dat_i[23:16];
+ 2'b10 : load_result_r[7:0] = mem_dat_i[15:8];
+ 2'b11 : load_result_r[7:0] = mem_dat_i[7:0];
+ default : ;
+ endcase
+
+ // Sign extend LB
+ if (inst_lbs_w && load_result_r[7])
+ load_result_r[31:8] = 24'hFFFFFF;
+ end
+
+ inst_lhs_w, // l.lhs
+ inst_lhz_w: // l.lhz
+ begin
+ case (mem_offset_q)
+ 2'b00 : load_result_r[15:0] = mem_dat_i[31:16];
+ 2'b10 : load_result_r[15:0] = mem_dat_i[15:0];
+ default : ;
+ endcase
+
+ // Sign extend LH
+ if (inst_lhs_w && load_result_r[15])
+ load_result_r[31:16] = 16'hFFFF;
+ end
+
+ // l.lwz l.lws
+ default :
+ load_result_r = 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
+ putc_q <= 8'b0;
+ `endif
+ end
+ else
+ begin
+ `ifdef SIM_EXT_PUTC
+ putc_q <= 8'b0;
+ `endif
+ if (inst_nop_w && state_q == STATE_EXEC)
+ begin
+ case (uint16_r)
+ // NOP_PUTC
+ 16'h0004:
+ begin
+ `ifdef SIM_EXT_PUTC
+ putc_q <= 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_q == STATE_EXEC) ? opcode_q : `OPCODE_INST_BUBBLE;
+ endfunction
+ function [31:0] get_pc_ex;
+ // verilator public
+ get_pc_ex = pc_q;
+ endfunction
+ function [7:0] get_putc;
+ // verilator public
+ `ifdef SIM_EXT_PUTC
+ get_putc = putc_q;
+ `else
+ get_putc = 8'b0;
+ `endif
+ endfunction
+ function [0:0] get_reg_valid;
+ // verilator public
+ get_reg_valid = (state_q == STATE_EXEC) ? 1'b1 : 1'b0;
+ endfunction
+ function [4:0] get_reg_ra;
+ // verilator public
+ get_reg_ra = ra_w;
+ endfunction
+ function [31:0] get_reg_ra_value;
+ // verilator public
+ get_reg_ra_value = reg_ra_w;
+ endfunction
+ function [4:0] get_reg_rb;
+ // verilator public
+ get_reg_rb = rb_w;
+ endfunction
+ function [31:0] get_reg_rb_value;
+ // verilator public
+ get_reg_rb_value = reg_rb_w;
+ endfunction
+`endif
+
+endmodule
altor32/rtl/cpu_lite/altor32_lite.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_regfile_alt.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_regfile_alt.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_regfile_alt.v (revision 25)
@@ -0,0 +1,184 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+ input [4:0] rd_i /*verilator public*/,
+ output reg [31:0] reg_ra_o /*verilator public*/,
+ output reg [31:0] reg_rb_o /*verilator public*/,
+ input [31:0] reg_rd_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter SUPPORT_32REGS = "ENABLED";
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+wire clk_delayed_w;
+wire [31:0] reg_ra_w;
+wire [31:0] reg_rb_w;
+wire write_enable_w;
+
+reg [4:0] addr_q;
+reg [31:0] data_q;
+
+wire [31:0] ra_w;
+wire [31:0] rb_w;
+
+//-----------------------------------------------------------------
+// Sync addr & data
+//-----------------------------------------------------------------
+always @ (posedge clk_i or posedge rst_i)
+begin
+ if (rst_i)
+ begin
+ addr_q <= 5'b00000;
+ data_q <= 32'h00000000;
+
+ end
+ else
+ begin
+ addr_q <= rd_i;
+ data_q <= 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_w),
+ .rdclken(1'b1),
+ .rdaddress(ra_i),
+ .rden(1'b1),
+ .data(reg_rd_i),
+ .wraddress(rd_i),
+ .wren(write_enable_w),
+ .wrclock(clk_i),
+ .wrclken(1'b1),
+ .q(ra_w)
+);
+
+
+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_w),
+ .rdclken(1'b1),
+ .rdaddress(rb_i),
+ .rden(1'b1),
+ .data(reg_rd_i),
+ .wraddress(rd_i),
+ .wren(write_enable_w),
+ .wrclock(clk_i),
+ .wrclken(1'b1),
+ .q(rb_w)
+);
+
+//-----------------------------------------------------------------
+// Combinatorial Assignments
+//-----------------------------------------------------------------
+
+// Delayed clock
+assign clk_delayed_w = !clk_i;
+
+// Register read ports
+always @ *
+begin
+ if (ra_i == 5'b00000)
+ reg_ra_o = 32'h00000000;
+ else
+ reg_ra_o = reg_ra_w;
+
+ if (rb_i == 5'b00000)
+ reg_rb_o = 32'h00000000;
+ else
+ reg_rb_o = reg_rb_w;
+end
+
+assign write_enable_w = (rd_i != 5'b00000) & wr_i;
+
+// Reads are bypassed during write-back
+assign reg_ra_w = (ra_i != addr_q) ? ra_w : data_q;
+assign reg_rb_w = (rb_i != addr_q) ? rb_w : data_q;
+
+endmodule
altor32/rtl/cpu_lite/altor32_regfile_alt.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_regfile_sim.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_regfile_sim.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_regfile_sim.v (revision 25)
@@ -0,0 +1,441 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+ input [4:0] rd_i /*verilator public*/,
+ output reg [31:0] reg_ra_o /*verilator public*/,
+ output reg [31:0] reg_rb_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 (ra_i)
+ 5'b00000 :
+ reg_ra_o = 32'h00000000;
+ 5'b00001 :
+ reg_ra_o = reg_r1_sp;
+ 5'b00010 :
+ reg_ra_o = reg_r2_fp;
+ 5'b00011 :
+ reg_ra_o = reg_r3;
+ 5'b00100 :
+ reg_ra_o = reg_r4;
+ 5'b00101 :
+ reg_ra_o = reg_r5;
+ 5'b00110 :
+ reg_ra_o = reg_r6;
+ 5'b00111 :
+ reg_ra_o = reg_r7;
+ 5'b01000 :
+ reg_ra_o = reg_r8;
+ 5'b01001 :
+ reg_ra_o = reg_r9_lr;
+ 5'b01010 :
+ reg_ra_o = reg_r10;
+ 5'b01011 :
+ reg_ra_o = reg_r11;
+ 5'b01100 :
+ reg_ra_o = reg_r12;
+ 5'b01101 :
+ reg_ra_o = reg_r13;
+ 5'b01110 :
+ reg_ra_o = reg_r14;
+ 5'b01111 :
+ reg_ra_o = reg_r15;
+ 5'b10000 :
+ reg_ra_o = reg_r16;
+ 5'b10001 :
+ reg_ra_o = reg_r17;
+ 5'b10010 :
+ reg_ra_o = reg_r18;
+ 5'b10011 :
+ reg_ra_o = reg_r19;
+ 5'b10100 :
+ reg_ra_o = reg_r20;
+ 5'b10101 :
+ reg_ra_o = reg_r21;
+ 5'b10110 :
+ reg_ra_o = reg_r22;
+ 5'b10111 :
+ reg_ra_o = reg_r23;
+ 5'b11000 :
+ reg_ra_o = reg_r24;
+ 5'b11001 :
+ reg_ra_o = reg_r25;
+ 5'b11010 :
+ reg_ra_o = reg_r26;
+ 5'b11011 :
+ reg_ra_o = reg_r27;
+ 5'b11100 :
+ reg_ra_o = reg_r28;
+ 5'b11101 :
+ reg_ra_o = reg_r29;
+ 5'b11110 :
+ reg_ra_o = reg_r30;
+ 5'b11111 :
+ reg_ra_o = reg_r31;
+ default :
+ reg_ra_o = 32'h00000000;
+ endcase
+
+ case (rb_i)
+ 5'b00000 :
+ reg_rb_o = 32'h00000000;
+ 5'b00001 :
+ reg_rb_o = reg_r1_sp;
+ 5'b00010 :
+ reg_rb_o = reg_r2_fp;
+ 5'b00011 :
+ reg_rb_o = reg_r3;
+ 5'b00100 :
+ reg_rb_o = reg_r4;
+ 5'b00101 :
+ reg_rb_o = reg_r5;
+ 5'b00110 :
+ reg_rb_o = reg_r6;
+ 5'b00111 :
+ reg_rb_o = reg_r7;
+ 5'b01000 :
+ reg_rb_o = reg_r8;
+ 5'b01001 :
+ reg_rb_o = reg_r9_lr;
+ 5'b01010 :
+ reg_rb_o = reg_r10;
+ 5'b01011 :
+ reg_rb_o = reg_r11;
+ 5'b01100 :
+ reg_rb_o = reg_r12;
+ 5'b01101 :
+ reg_rb_o = reg_r13;
+ 5'b01110 :
+ reg_rb_o = reg_r14;
+ 5'b01111 :
+ reg_rb_o = reg_r15;
+ 5'b10000 :
+ reg_rb_o = reg_r16;
+ 5'b10001 :
+ reg_rb_o = reg_r17;
+ 5'b10010 :
+ reg_rb_o = reg_r18;
+ 5'b10011 :
+ reg_rb_o = reg_r19;
+ 5'b10100 :
+ reg_rb_o = reg_r20;
+ 5'b10101 :
+ reg_rb_o = reg_r21;
+ 5'b10110 :
+ reg_rb_o = reg_r22;
+ 5'b10111 :
+ reg_rb_o = reg_r23;
+ 5'b11000 :
+ reg_rb_o = reg_r24;
+ 5'b11001 :
+ reg_rb_o = reg_r25;
+ 5'b11010 :
+ reg_rb_o = reg_r26;
+ 5'b11011 :
+ reg_rb_o = reg_r27;
+ 5'b11100 :
+ reg_rb_o = reg_r28;
+ 5'b11101 :
+ reg_rb_o = reg_r29;
+ 5'b11110 :
+ reg_rb_o = reg_r30;
+ 5'b11111 :
+ reg_rb_o = reg_r31;
+ default :
+ reg_rb_o = 32'h00000000;
+ endcase
+ end
+end
+else
+begin
+ // Asynchronous Register read (Rs & Rd)
+ always @ *
+ begin
+ case (ra_i)
+ 5'b00000 :
+ reg_ra_o = 32'h00000000;
+ 5'b00001 :
+ reg_ra_o = reg_r1_sp;
+ 5'b00010 :
+ reg_ra_o = reg_r2_fp;
+ 5'b00011 :
+ reg_ra_o = reg_r3;
+ 5'b00100 :
+ reg_ra_o = reg_r4;
+ 5'b00101 :
+ reg_ra_o = reg_r5;
+ 5'b00110 :
+ reg_ra_o = reg_r6;
+ 5'b00111 :
+ reg_ra_o = reg_r7;
+ 5'b01000 :
+ reg_ra_o = reg_r8;
+ 5'b01001 :
+ reg_ra_o = reg_r9_lr;
+ 5'b01010 :
+ reg_ra_o = reg_r10;
+ 5'b01011 :
+ reg_ra_o = reg_r11;
+ 5'b01100 :
+ reg_ra_o = reg_r12;
+ 5'b01101 :
+ reg_ra_o = reg_r13;
+ 5'b01110 :
+ reg_ra_o = reg_r14;
+ 5'b01111 :
+ reg_ra_o = reg_r15;
+ default :
+ reg_ra_o = 32'h00000000;
+ endcase
+
+ case (rb_i)
+ 5'b00000 :
+ reg_rb_o = 32'h00000000;
+ 5'b00001 :
+ reg_rb_o = reg_r1_sp;
+ 5'b00010 :
+ reg_rb_o = reg_r2_fp;
+ 5'b00011 :
+ reg_rb_o = reg_r3;
+ 5'b00100 :
+ reg_rb_o = reg_r4;
+ 5'b00101 :
+ reg_rb_o = reg_r5;
+ 5'b00110 :
+ reg_rb_o = reg_r6;
+ 5'b00111 :
+ reg_rb_o = reg_r7;
+ 5'b01000 :
+ reg_rb_o = reg_r8;
+ 5'b01001 :
+ reg_rb_o = reg_r9_lr;
+ 5'b01010 :
+ reg_rb_o = reg_r10;
+ 5'b01011 :
+ reg_rb_o = reg_r11;
+ 5'b01100 :
+ reg_rb_o = reg_r12;
+ 5'b01101 :
+ reg_rb_o = reg_r13;
+ 5'b01110 :
+ reg_rb_o = reg_r14;
+ 5'b01111 :
+ reg_rb_o = reg_r15;
+ default :
+ reg_rb_o = 32'h00000000;
+ endcase
+ end
+end
+endgenerate
+
+endmodule
altor32/rtl/cpu_lite/altor32_regfile_sim.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/rtl/cpu_lite/altor32_regfile_xil.v
===================================================================
--- altor32/rtl/cpu_lite/altor32_regfile_xil.v (nonexistent)
+++ altor32/rtl/cpu_lite/altor32_regfile_xil.v (revision 25)
@@ -0,0 +1,136 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2014
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2014 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] ra_i /*verilator public*/,
+ input [4:0] rb_i /*verilator public*/,
+ input [4:0] rd_i /*verilator public*/,
+ output reg [31:0] reg_ra_o /*verilator public*/,
+ output reg [31:0] reg_rb_o /*verilator public*/,
+ input [31:0] reg_rd_i /*verilator public*/
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter SUPPORT_32REGS = "ENABLED";
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+wire [31:0] reg_ra_w;
+wire [31:0] reg_rb_w;
+wire [31:0] ra_0_15_w;
+wire [31:0] ra_16_31_w;
+wire [31:0] rb_0_15_w;
+wire [31:0] rb_16_31_w;
+wire write_enable_w;
+wire write_banka_w;
+wire write_bankb_w;
+
+//-----------------------------------------------------------------
+// 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(write_banka_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(ra_0_15_w[i]), .SPO(/* open */));
+ RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(write_banka_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rb_0_15_w[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_bit1b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(ra_16_31_w[i]), .SPO(/* open */));
+ RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rb_16_31_w[i]), .SPO(/* open */));
+ end
+end
+else
+begin
+ assign ra_16_31_w = 32'h00000000;
+ assign rb_16_31_w = 32'h00000000;
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Combinatorial Assignments
+//-----------------------------------------------------------------
+assign reg_ra_w = (ra_i[4] == 1'b0) ? ra_0_15_w : ra_16_31_w;
+assign reg_rb_w = (rb_i[4] == 1'b0) ? rb_0_15_w : rb_16_31_w;
+
+assign write_enable_w = (rd_i != 5'b00000) & wr_i;
+
+assign write_banka_w = (write_enable_w & (~rd_i[4]));
+assign write_bankb_w = (write_enable_w & rd_i[4]);
+
+// Register read ports
+always @ *
+begin
+ if (ra_i == 5'b00000)
+ reg_ra_o = 32'h00000000;
+ else
+ reg_ra_o = reg_ra_w;
+
+ if (rb_i == 5'b00000)
+ reg_rb_o = 32'h00000000;
+ else
+ reg_rb_o = reg_rb_w;
+end
+
+endmodule
altor32/rtl/cpu_lite/altor32_regfile_xil.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/sw/boot.S
===================================================================
--- altor32/sw/boot.S (nonexistent)
+++ altor32/sw/boot.S (revision 25)
@@ -0,0 +1,148 @@
+.nodelay
+
+#include "exception.inc"
+
+
+#-------------------------------------------------------------
+# VECTOR 0x100 - Reset
+#-------------------------------------------------------------
+.org 0x100
+vector_reset:
+
+ # Setup SP (R1)
+ l.movhi r4,hi(_sp);
+ l.ori r1,r4,lo(_sp);
+
+ # R4 = _bss_start
+ l.movhi r4,hi(_bss_start);
+ l.ori r4,r4,lo(_bss_start);
+
+ # R5 = _bss_end
+ l.movhi r5,hi(_bss_end);
+ l.ori r5,r5,lo(_bss_end);
+
+BSS_CLEAR:
+ l.sw 0x0(r4),r0 # Write 0x00 to mem[r4]
+ l.sfleu r4,r5 # SR[F] = (r4 < r5)
+ l.addi r4, r4, 4 # r4 += 4
+ l.bf BSS_CLEAR # If SR[F] == 0, jump to BSS_CLEAR
+ l.nop
+
+ # Jump to debug agent
+ l.j main
+ l.nop
+
+.size vector_reset, .-vector_reset
+
+#-------------------------------------------------------------
+# VECTOR 0x200 - Fault / Illegal Instruction
+#-------------------------------------------------------------
+.org 0x200
+vector_fault:
+
+ # Save context
+ asm_save_context
+
+ # Arg 2 = Fault
+ l.addi r4, r0, 1
+
+ l.j handle_exception
+ l.nop
+
+.size vector_fault, .-vector_fault
+
+#-------------------------------------------------------------
+# VECTOR 0x300 - External Interrupt
+#-------------------------------------------------------------
+.org 0x300
+vector_extint:
+
+ # Save context
+ asm_save_context
+
+ # Arg 2 = Ext Int
+ l.addi r4, r0, 2
+
+ l.j handle_exception
+ l.nop
+
+.size vector_extint, .-vector_extint
+
+#-------------------------------------------------------------
+# VECTOR 0x400 - Syscall
+#-------------------------------------------------------------
+.org 0x400
+vector_syscall:
+
+ # Save context
+ asm_save_context
+
+ # Arg 2 = Syscall
+ l.addi r4, r0, 3
+
+ l.j handle_exception
+ l.nop
+
+.size vector_syscall, .-vector_syscall
+
+#-------------------------------------------------------------
+# VECTOR 0x600 - Trap
+#-------------------------------------------------------------
+.org 0x600
+vector_trap:
+
+ # Save context
+ asm_save_context
+
+ # Arg 2 = Trap
+ l.addi r4, r0, 4
+
+ # Fall through...
+
+.size vector_trap, .-vector_trap
+
+#-------------------------------------------------------------
+# handle_exception: Common exception handling code
+#-------------------------------------------------------------
+handle_exception:
+
+ # Copy stack pointer to arg1
+ l.add r3, r0, r1
+
+ # Jump to debug handler
+ l.movhi r10,hi(exception);
+ l.ori r10,r10,lo(exception);
+ l.jalr r10
+ l.nop
+
+ # Return value is stack pointer
+ l.add r1, r0, r11
+
+ # Restore context
+ asm_load_context
+
+.size handle_exception, .-handle_exception
+
+
+#------------------------------------
+#
+#------------------------------------
+
+hang:
+ l.trap 0
+ l.j hang
+ l.nop
+
+.globl PUT32
+PUT32:
+ l.jr r9
+ l.sw 0(r3),r4
+
+.globl GET32
+GET32:
+ l.jr r9
+ l.lwz r11,0(r3)
+
+ l.j hang
+ l.nop
+
altor32/sw/boot.S
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/sw/common/cache.c
===================================================================
--- altor32/sw/common/cache.c (nonexistent)
+++ altor32/sw/common/cache.c (revision 25)
@@ -0,0 +1,50 @@
+#include "cache.h"
+
+//-----------------------------------------------------------------
+// Defines:
+//-----------------------------------------------------------------
+// SR Register
+#define SPR_SR (17)
+#define SPR_SR_ICACHE_FLUSH (1 << 17)
+#define SPR_SR_DCACHE_FLUSH (1 << 18)
+
+//-----------------------------------------------------------------
+// mfspr: Read from SPR
+//-----------------------------------------------------------------
+static inline unsigned long mfspr(unsigned long spr)
+{
+ unsigned long value;
+ asm volatile ("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
+ return value;
+}
+//-----------------------------------------------------------------
+// mtspr: Write to SPR
+//-----------------------------------------------------------------
+static inline void mtspr(unsigned long spr, unsigned long value)
+{
+ asm volatile ("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
+}
+//-----------------------------------------------------------------
+// cache_dflush:
+//-----------------------------------------------------------------
+void cache_dflush(void)
+{
+ unsigned long sr = mfspr(SPR_SR);
+ mtspr(SPR_SR, sr | SPR_SR_DCACHE_FLUSH);
+}
+//-----------------------------------------------------------------
+// cache_iflush:
+//-----------------------------------------------------------------
+void cache_iflush(void)
+{
+ unsigned long sr = mfspr(SPR_SR);
+ mtspr(SPR_SR, sr | SPR_SR_ICACHE_FLUSH);
+}
+//-----------------------------------------------------------------
+// cache_flush:
+//-----------------------------------------------------------------
+void cache_flush(void)
+{
+ unsigned long sr = mfspr(SPR_SR);
+ mtspr(SPR_SR, sr | SPR_SR_ICACHE_FLUSH | SPR_SR_DCACHE_FLUSH);
+}
Index: altor32/sw/common/cache.h
===================================================================
--- altor32/sw/common/cache.h (nonexistent)
+++ altor32/sw/common/cache.h (revision 25)
@@ -0,0 +1,11 @@
+#ifndef __CACHE_H__
+#define __CACHE_H__
+
+//-----------------------------------------------------------------
+// Prototypes:
+//-----------------------------------------------------------------
+void cache_dflush(void);
+void cache_iflush(void);
+void cache_flush(void);
+
+#endif // __CACHE_H__
Index: altor32/sw/common/irq.h
===================================================================
--- altor32/sw/common/irq.h (nonexistent)
+++ altor32/sw/common/irq.h (revision 25)
@@ -0,0 +1,23 @@
+#include "irq.h"
+
+//-----------------------------------------------------------------
+// irq_enable
+//-----------------------------------------------------------------
+void irq_enable(int interrupt)
+{
+ IRQ_MASK_SET = (1 << interrupt);
+}
+//-----------------------------------------------------------------
+// irq_disable
+//-----------------------------------------------------------------
+void irq_disable(int interrupt)
+{
+ IRQ_MASK_CLR = (1 << interrupt);
+}
+//-----------------------------------------------------------------
+// irq_acknowledge
+//-----------------------------------------------------------------
+void irq_acknowledge(int interrupt)
+{
+ IRQ_STATUS = (1 << interrupt);
+}
Index: altor32/sw/exception.inc
===================================================================
--- altor32/sw/exception.inc (nonexistent)
+++ altor32/sw/exception.inc (revision 25)
@@ -0,0 +1,157 @@
+#-------------------------------------------------------------
+# Context Stack Frame - 140 bytes / 35 words
+#-------------------------------------------------------------
+# 0: R0
+# 4: R1 (SP)
+# 8: R2
+# 12: R3 (ARG0)
+# 16: R4
+# 20: R5
+# 24: R6
+# 28: R7
+# 32: R8
+# 36: R9 (LR)
+# 40: R10
+# 44: R11
+# 48: R12
+# 52: R13
+# 56: R14
+# 60: R15
+# 64: R16
+# 68: R17
+# 72: R18
+# 76: R19
+# 80: R20
+# 84: R21
+# 88: R22
+# 92: R23
+# 96: R24
+# 100: R25
+# 104: R26
+# 108: R27
+# 112: R28
+# 116: R29
+# 120: R30
+# 124: R31
+# 128: X
+# 132: EPC
+# 136: ESR
+#-------------------------------------------------------------
+
+#-------------------------------------------------------------
+# asm_save_context:
+#-------------------------------------------------------------
+.macro asm_save_context
+
+ l.nop
+ l.nop
+
+ # Adjust SP (frame size is 140 + allow for 128 uncommitted in-use stack)
+ l.addi r1, r1, -268
+
+ # Save register file to stack
+ l.sw 124(r1), r31
+ l.sw 120(r1), r30
+ l.sw 116(r1), r29
+ l.sw 112(r1), r28
+ l.sw 108(r1), r27
+ l.sw 104(r1), r26
+ l.sw 100(r1), r25
+ l.sw 96(r1), r24
+ l.sw 92(r1), r23
+ l.sw 88(r1), r22
+ l.sw 84(r1), r21
+ l.sw 80(r1), r20
+ l.sw 76(r1), r19
+ l.sw 72(r1), r18
+ l.sw 68(r1), r17
+ l.sw 64(r1), r16
+ l.sw 60(r1), r15
+ l.sw 56(r1), r14
+ l.sw 52(r1), r13
+ l.sw 48(r1), r12
+ l.sw 44(r1), r11
+ l.sw 40(r1), r10
+ l.sw 36(r1), r9
+ l.sw 32(r1), r8
+ l.sw 28(r1), r7
+ l.sw 24(r1), r6
+ l.sw 20(r1), r5
+ l.sw 16(r1), r4
+ l.sw 12(r1), r3
+ l.sw 8(r1), r2
+ l.sw 0(r1), r0
+
+ # R10 = EPC
+ l.mfspr r10, r0, 32
+ l.sw 132(r1), r10
+
+ # R10 = ESR
+ l.mfspr r10, r0, 64
+ l.sw 136(r1), r10
+
+ # Stack pointer (R1)
+ l.or r10, r0, r1
+ l.addi r10, r10, +268
+ l.sw 4(r1), r10
+
+.endm
+
+#-------------------------------------------------------------
+# asm_load_context:
+#-------------------------------------------------------------
+.macro asm_load_context
+
+ # Restore EPC (PC of non-exception code)
+ l.lwz r10, 132(r1)
+
+ # EPC = R10
+ l.mtspr r0,r10,32
+
+ # Restore ESR (SR of non-exception code)
+ l.lwz r10, 136(r1)
+
+ # ESR = R10
+ l.mtspr r0,r10,64
+
+ # Restore register set
+ # r1/r1 already set
+ l.lwz r2, 8(r1)
+ l.lwz r3, 12(r1)
+ l.lwz r4, 16(r1)
+ l.lwz r5, 20(r1)
+ l.lwz r6, 24(r1)
+ l.lwz r7, 28(r1)
+ l.lwz r8, 32(r1)
+ l.lwz r9, 36(r1)
+ l.lwz r10, 40(r1)
+ l.lwz r11, 44(r1)
+ l.lwz r12, 48(r1)
+ l.lwz r13, 52(r1)
+ l.lwz r14, 56(r1)
+ l.lwz r15, 60(r1)
+ l.lwz r16, 64(r1)
+ l.lwz r17, 68(r1)
+ l.lwz r18, 72(r1)
+ l.lwz r19, 76(r1)
+ l.lwz r20, 80(r1)
+ l.lwz r21, 84(r1)
+ l.lwz r22, 88(r1)
+ l.lwz r23, 92(r1)
+ l.lwz r24, 96(r1)
+ l.lwz r25,100(r1)
+ l.lwz r26,104(r1)
+ l.lwz r27,108(r1)
+ l.lwz r28,112(r1)
+ l.lwz r29,116(r1)
+ l.lwz r30,120(r1)
+ l.lwz r31,124(r1)
+
+ # Adjust SP past register set
+ l.addi r1, r1, +268
+
+ # Return from interrupt (to restore PC & SR)
+ l.rfe
+ l.nop
+
+.endm
altor32/sw/exception.inc
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/sw/linker_script
===================================================================
--- altor32/sw/linker_script (nonexistent)
+++ altor32/sw/linker_script (revision 25)
@@ -0,0 +1,53 @@
+GROUP("libgcc.a")
+
+MEMORY
+{
+ sram (rwx) : ORIGIN = 0x00000000, LENGTH = 8K
+}
+
+SECTIONS
+{
+ .text :
+ {
+ _text_start = .;
+ *(.text .text.*) /* remaining code */
+ *(.rodata) /* read-only data (constants) */
+ *(.rodata*)
+ *(.rdata*)
+ . = ALIGN(4);
+ _text_end = .;
+ } > sram
+
+ .data :
+ {
+ . = ALIGN(4);
+ _data_start = .;
+
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(16);
+ . = ALIGN (8);
+ *(.ram)
+ *(.eh_frame)
+ . = ALIGN (8);
+ _edata = .;
+ _data_end = .;
+ } > sram
+
+ .bss :
+ {
+ . = ALIGN(4);
+ _bss_start = . ;
+
+ *(.bss*)
+ *(COMMON)
+
+ /* Allocate room for stack */
+ . = ALIGN(8) ;
+ . += 1024 ;
+ _sp = . - 16;
+
+ _bss_end = .;
+ } > sram
+}
altor32/sw/linker_script
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/sw/makefile
===================================================================
--- altor32/sw/makefile (nonexistent)
+++ altor32/sw/makefile (revision 25)
@@ -0,0 +1,91 @@
+TOOLCHAIN=$(PRONOC_WORK)/toolchain
+IHEX2MIF =$(TOOLCHAIN)/bin/ihex2mif
+IHEX2BIN =$(TOOLCHAIN)/bin/ihex2bin
+OR1K_TCHAIN= $(TOOLCHAIN)/or1k/bin/or1knd-elf
+
+###############################################################################
+# Configuration
+###############################################################################
+# Target
+TARGET ?= main
+
+# Memory Layout
+MEMBASE ?= 0x00000000
+MEMSIZE ?= 12384
+MEMNAME ?= sram
+
+###############################################################################
+# Files
+###############################################################################
+INCLUDE_DIRS ?=
+OBJ = boot.o
+OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
+OBJ+= $(OBJS)
+
+###############################################################################
+## Makefile
+###############################################################################
+
+# Tools
+
+
+CC = $(OR1K_TCHAIN)-gcc $(CFLAGS)
+AS = $(OR1K_TCHAIN)-as
+LD = $(OR1K_TCHAIN)-ld
+OBJDUMP = $(OR1K_TCHAIN)-objdump
+OBJCOPY = $(OR1K_TCHAIN)-objcopy
+
+# Options
+CFLAGS ?=
+CFLAGS += -Ttext $(MEMBASE) -Os -g -Wall
+CFLAGS += -msoft-div -msoft-float -msoft-mul -mno-ror -mno-cmov -mno-sext
+CFLAGS += -nostartfiles -nodefaultlibs -nostdlib -lgcc -L .
+ASFLAGS =
+LDFLAGS =
+
+LDSCRIPT= linker_script
+CFLAGS += -mno-delay -D__OR1K_NODELAY__ -D__OR1K__
+ASFLAGS+= -mno-delay -Wa,--defsym,__OR1K_NODELAY__=1
+CFLAGS += -T$(LDSCRIPT)
+SIMARGS += -n
+
+CFLAGS += -I. $(INCLUDE_DIRS)
+
+RAMSIZE ?= "7FFF"
+###############################################################################
+# Rules
+###############################################################################
+conv: all
+# Convert the ELF file to an IHEX file
+ $(OBJCOPY) -O ihex $(TARGET).elf $(TARGET).ihex
+# Generate a MIF file from the IHEX file
+ $(IHEX2MIF) -f $(TARGET).ihex -e $(RAMSIZE) -o ram0.mif
+ $(IHEX2BIN) -f $(TARGET).ihex -o ram0.bin
+
+
+all: $(TARGET).elf lst bin
+
+
+
+
+clean:
+ -rm $(OBJ) *.map *.lst *.hex *.ver *.txt *.elf *.ihex $(TARGET).bin ram0.mif
+
+%.o : %.s
+ $(CC) -c $(ASFLAGS) $< -o $@
+
+%.o : %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(TARGET).elf: $(OBJ) $(LDSCRIPT) makefile
+ $(CC) $(LDFLAGS) $(LIBS) $(OBJ) -o $@
+
+lst: $(TARGET).lst
+
+%.lst: $(TARGET).elf
+ $(OBJDUMP) -h -d -S $< > $@
+
+bin: $(TARGET).bin
+
+%.bin: %.elf
+ $(OBJCOPY) -O binary $< $@
altor32/sw/makefile
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: altor32/sw/program/prog.tcl
===================================================================
--- altor32/sw/program/prog.tcl (nonexistent)
+++ altor32/sw/program/prog.tcl (revision 25)
@@ -0,0 +1,80 @@
+#/usr/bin/tclsh
+
+proc hold_reset {} {
+ global device_name usb
+ start_insystem_source_probe -device_name $device_name -hardware_name $usb
+ write_source_data -instance_index 127 -value 0x1 -value_in_hex
+ end_insystem_source_probe
+}
+
+proc release_reset {} {
+ global device_name usb
+ start_insystem_source_probe -device_name $device_name -hardware_name $usb
+ write_source_data -instance_index 127 -value 0x0 -value_in_hex
+ end_insystem_source_probe
+}
+
+## Setup USB hardware - assumes only USB Blaster is installed and
+## an FPGA is the only device in the JTAG chain
+set usb [lindex [get_hardware_names] 0]
+set device_name [lindex [get_device_names -hardware_name $usb] 0]
+
+puts $usb
+puts $device_name
+
+#reset all processors
+hold_reset
+
+
+# Initiate a editing sequence
+begin_memory_edit -hardware_name $usb -device_name $device_name
+
+foreach instance \
+ [get_editable_mem_instances -hardware_name $usb -device_name $device_name] {
+ set inst_name [lindex $instance 5]
+ set inst_index [lindex $instance 0]
+ puts $inst_name
+ puts $inst_index
+ #set xx [string range $inst_name 0 1]
+ #set yy [string range $inst_name 2 end]
+ #puts $xx
+ #puts $yy
+ set ram_file_name ../ram${inst_name}.mif
+
+#update prog memory
+ if {[file exists $ram_file_name] == 1} {
+ puts "memory ${inst_name} is programed with $ram_file_name"
+ update_content_to_memory_from_file -instance_index $inst_index -mem_file_path $ram_file_name -mem_file_type mif
+ } else {
+ puts "file $ram_file_name does not exist! memory ${inst_name} left unprogramed"
+ }
+
+}
+
+
+
+
+#set xx 0
+#set yy 0
+# for {set yy 0} {$yy<$Y_NODE_NUM} {incr yy} {
+# for {set xx 0} {$xx<$X_NODE_NUM} {incr xx} {
+# set ram_file_name [format "ram/cpu%02d_%02d.mif" $xx $yy]
+# set mem_index [format "%02d%02d" $xx $yy]
+
+#update prog memory
+# update_content_to_memory_from_file -instance_index $mem_index -mem_file_path $ram_file_name -mem_file_type mif
+
+#puts $ram_file_name\n
+#puts $mem_index\n
+
+# }}
+
+
+
+
+
+#End the editing sequence
+end_memory_edit
+
+#release reset
+release_reset
altor32/sw/program/prog.tcl
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lm32/sw/Makefile
===================================================================
--- lm32/sw/Makefile (revision 21)
+++ lm32/sw/Makefile (revision 25)
@@ -1,5 +1,6 @@
TOOLCHAIN=$(PRONOC_WORK)/toolchain/lm32
-IHEX2MIF =$(PRONOC_WORK)/toolchain/ihex2mif/ihex2mif
+IHEX2MIF =$(PRONOC_WORK)/toolchain/bin/ihex2mif
+IHEX2BIN =$(PRONOC_WORK)/toolchain/bin/ihex2bin
#SREC2VRAM ?= ../../../toolchain/lm32/srec2vram/srec2vram
@@ -51,7 +52,8 @@
$(VRAMFILE): image.srec
#$(SREC2VRAM) image.srec 0x40000000 0x1000 > $(VRAMFILE)
- $(IHEX2MIF) -f image.ihex -e $(RAMSIZE) -o ram00.mif
+ $(IHEX2MIF) -f image.ihex -e $(RAMSIZE) -o ram0.mif
+ $(IHEX2BIN) -i image.ihex -o ram0.bin
clean:
rm -f image.ihex image image.lst image.bin image.srec image.map image.ram image.hex *.o *.d
/lm32/sw/program/prog.tcl
0,0 → 1,80
#/usr/bin/tclsh |
|
proc hold_reset {} { |
global device_name usb |
start_insystem_source_probe -device_name $device_name -hardware_name $usb |
write_source_data -instance_index 127 -value 0x1 -value_in_hex |
end_insystem_source_probe |
} |
|
proc release_reset {} { |
global device_name usb |
start_insystem_source_probe -device_name $device_name -hardware_name $usb |
write_source_data -instance_index 127 -value 0x0 -value_in_hex |
end_insystem_source_probe |
} |
|
## Setup USB hardware - assumes only USB Blaster is installed and |
## an FPGA is the only device in the JTAG chain |
set usb [lindex [get_hardware_names] 0] |
set device_name [lindex [get_device_names -hardware_name $usb] 0] |
|
puts $usb |
puts $device_name |
|
#reset all processors |
hold_reset |
|
|
# Initiate a editing sequence |
begin_memory_edit -hardware_name $usb -device_name $device_name |
|
foreach instance \ |
[get_editable_mem_instances -hardware_name $usb -device_name $device_name] { |
set inst_name [lindex $instance 5] |
set inst_index [lindex $instance 0] |
puts $inst_name |
puts $inst_index |
#set xx [string range $inst_name 0 1] |
#set yy [string range $inst_name 2 end] |
#puts $xx |
#puts $yy |
set ram_file_name ../ram${inst_name}.mif |
|
#update prog memory |
if {[file exists $ram_file_name] == 1} { |
puts "memory ${inst_name} is programed with $ram_file_name" |
update_content_to_memory_from_file -instance_index $inst_index -mem_file_path $ram_file_name -mem_file_type mif |
} else { |
puts "file $ram_file_name does not exist! memory ${inst_name} left unprogramed" |
} |
|
} |
|
|
|
|
#set xx 0 |
#set yy 0 |
# for {set yy 0} {$yy<$Y_NODE_NUM} {incr yy} { |
# for {set xx 0} {$xx<$X_NODE_NUM} {incr xx} { |
# set ram_file_name [format "ram/cpu%02d_%02d.mif" $xx $yy] |
# set mem_index [format "%02d%02d" $xx $yy] |
|
#update prog memory |
# update_content_to_memory_from_file -instance_index $mem_index -mem_file_path $ram_file_name -mem_file_type mif |
|
#puts $ram_file_name\n |
#puts $mem_index\n |
|
# }} |
|
|
|
|
|
#End the editing sequence |
end_memory_edit |
|
#release reset |
release_reset |
lm32/sw/program/prog.tcl
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lm32/verilog/src/lm32.v
===================================================================
--- lm32/verilog/src/lm32.v (revision 21)
+++ lm32/verilog/src/lm32.v (revision 25)
@@ -14,6 +14,7 @@
clk_i,
rst_i,
interrupt,
+ en_i,
// Instruction Wishbone master
I_DAT_I,
I_ACK_I,
@@ -50,7 +51,13 @@
input clk_i; // Clock
input rst_i; // Reset
+input en_i;
+
+wire reset;
+
+assign reset = rst_i | ~ en_i;
+
//`ifdef CFG_INTERRUPTS_ENABLED
input [`LM32_INTERRUPT_RNG] interrupt; // Interrupt pins
//`endif
@@ -136,7 +143,7 @@
lm32_top the_lm32_top(
.clk_i(clk_i),
- .rst_i(rst_i),
+ .rst_i(reset ),
.interrupt_n(~interrupt),
.I_DAT_I(I_DAT_I),
.I_ACK_I(I_ACK_I),
@@ -176,3 +183,4 @@
endmodule
+
/program.sh
0,0 → 1,34
#!/bin/sh |
|
OFSSET="0x00000000" |
BOUNDRY="0x00003fff" |
BINFILE="ram0.bin" |
VJTAG_INDEX="0" |
|
JTAG_MAIN="$PRONOC_WORK/toolchain/bin/jtag_main" |
|
#reset and disable cpus, then release the reset but keep the cpus disabled |
|
$JTAG_MAIN -n 127 -d "I:1,D:2:3,D:2:2,I:0" |
|
# jtag instruction |
# 0: bypass |
# 1: getting data |
# jtag data : |
# bit 0 is reset |
# bit 1 is disable |
# I:1 set jtag_enable in active mode |
# D:2:3 load jtag_enable data register with 0x3 reset=1 disable=1 |
# D:2:2 load jtag_enable data register with 0x2 reset=0 disable=1 |
# I:0 set jtag_enable in bypass mode |
|
|
|
#programe the memory |
$JTAG_MAIN -n $VJTAG_INDEX -s $OFSSET -e $BOUNDRY -i $BINFILE -c |
|
#Enable the cpu |
$JTAG_MAIN -n 127 -d "I:1,D:2:0,I:0" |
# I:1 set jtag_enable in active mode |
# D:2:0 load jtag_enable data register with 0x0 reset=0 disable=0 |
# I:0 set jtag_enable in bypass mode |
program.sh
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property