OpenCores
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

powered by: WebSVN 2.1.0

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