OpenCores
URL https://opencores.org/ocsvn/altor32/altor32/trunk

Subversion Repositories altor32

[/] [altor32/] [trunk/] [rtl/] [cpu/] [altor32_fetch.v] - Diff between revs 27 and 36

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 27 Rev 36
Line 1... Line 1...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//                           AltOR32 
//                           AltOR32 
//                Alternative Lightweight OpenRisc 
//                Alternative Lightweight OpenRisc 
//                            V2.0
//                            V2.1
//                     Ultra-Embedded.com
//                     Ultra-Embedded.com
//                   Copyright 2011 - 2013
//                   Copyright 2011 - 2014
//
//
//               Email: admin@ultra-embedded.com
//               Email: admin@ultra-embedded.com
//
//
//                       License: LGPL
//                       License: LGPL
//-----------------------------------------------------------------
//-----------------------------------------------------------------
Line 33... Line 33...
// Public License along with this source; if not, write to the 
// Public License along with this source; if not, write to the 
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
// Boston, MA  02111-1307  USA
// Boston, MA  02111-1307  USA
//-----------------------------------------------------------------
//-----------------------------------------------------------------
 
 
//`define CONF_FETCH_DEBUG
 
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Includes
// Includes
//-----------------------------------------------------------------
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_defs.v"
 
 
Line 51... Line 49...
    input               clk_i /*verilator public*/,
    input               clk_i /*verilator public*/,
    input               rst_i /*verilator public*/,
    input               rst_i /*verilator public*/,
 
 
    // Instruction Fetch
    // Instruction Fetch
    output              fetch_o /*verilator public*/,
    output              fetch_o /*verilator public*/,
    output [31:0]       pc_o /*verilator public*/,
    output reg [31:0]   pc_o /*verilator public*/,
    input [31:0]        data_i /*verilator public*/,
    input [31:0]        data_i /*verilator public*/,
    input               data_valid_i/*verilator public*/,
    input               data_valid_i/*verilator public*/,
 
 
    // Branch target
    // Branch target
    input               branch_i /*verilator public*/,
    input               branch_i /*verilator public*/,
Line 76... Line 74...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Params
// Params
//-----------------------------------------------------------------
//-----------------------------------------------------------------
parameter           BOOT_VECTOR             = 32'h00000000;
parameter           BOOT_VECTOR             = 32'h00000000;
parameter           CACHE_LINE_SIZE_WIDTH   = 5; /* 5-bits -> 32 entries */
parameter           CACHE_LINE_SIZE_WIDTH   = 5; /* 5-bits -> 32 entries */
 
parameter           PIPELINED_FETCH         = "DISABLED";
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Registers
// Registers
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg [31:0]  r_pc;
 
reg         r_rd;
reg         r_rd;
reg [31:0]  r_last_opcode;
reg [31:0]  r_pc;
reg [31:0]  r_last_pc;
 
reg         r_last_valid;
 
reg [31:0]  d_pc;
reg [31:0]  d_pc;
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Next PC state machine
// Next PC state machine
//-------------------------------------------------------------------
//-------------------------------------------------------------------
reg [31:0] v_pc;
wire [31:0] next_pc = r_pc + 32'd4;
 
 
always @ (posedge clk_i or posedge rst_i)
always @ (posedge clk_i or posedge rst_i)
begin
begin
   if (rst_i)
   if (rst_i)
   begin
   begin
        r_pc        <= BOOT_VECTOR + `VECTOR_RESET;
        r_pc        <= BOOT_VECTOR + `VECTOR_RESET;
        d_pc        <= BOOT_VECTOR + `VECTOR_RESET;
        d_pc        <= BOOT_VECTOR + `VECTOR_RESET;
        r_rd        <= 1'b1;
        r_rd        <= 1'b1;
   end
   end
   else
   else if (~stall_i)
   begin
   begin
        r_rd        <= 1'b0;
        r_rd        <= 1'b0;
        d_pc        <= pc_o;
        d_pc        <= pc_o;
 
 
        // Branch - Next PC = branch target + 4
        // Branch - Next PC = branch target + 4
        if (branch_i)
        if (branch_i)
        begin
        begin
            r_pc <= branch_pc_i + 4;
            r_pc <= branch_pc_i + 4;
        end
        end
        // Stall - rollback to previous PC + 4
 
        else if (stall_i)
 
        begin
 
            r_pc <= d_pc + 4;
 
        end
 
        // Normal sequential execution (and instruction is ready)
        // Normal sequential execution (and instruction is ready)
        else if (data_valid_i)
        else if (data_valid_i)
        begin
        begin
            v_pc = r_pc + 4;
 
 
 
            // New cache line?
            // New cache line?
            if (v_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
            if (next_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
            begin
            begin
                // Start fetch of next line
                // Start fetch of next line
                r_rd  <= 1'b1;
                r_rd  <= 1'b1;
            end
            end
 
 
            r_pc <= v_pc;
            r_pc <= next_pc;
        end
        end
   end
   end
end
end
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Pipeline storage of last PC/opcode passed to exec stage
// Assignments
 
//-------------------------------------------------------------------
 
 
 
// Instruction Fetch
 
always @ *
 
begin
 
    // Stall, revert to last requested PC
 
    if (stall_i)
 
        pc_o = d_pc;
 
    else if (branch_i)
 
        pc_o = branch_pc_i;
 
    else if (~data_valid_i)
 
        pc_o = d_pc;
 
    else
 
        pc_o = r_pc;
 
end
 
 
 
assign fetch_o         = branch_i ? 1'b1 : r_rd;
 
 
 
//-------------------------------------------------------------------
 
// Opcode output (retiming)
//-------------------------------------------------------------------
//-------------------------------------------------------------------
 
generate
 
if (PIPELINED_FETCH == "ENABLED")
 
begin: FETCH_FLOPS
 
    reg [31:0] r_opcode;
 
    reg [31:0] r_opcode_pc;
 
    reg        r_opcode_valid;
 
    reg        r_branch;
 
 
always @ (posedge clk_i or posedge rst_i)
always @ (posedge clk_i or posedge rst_i)
begin
begin
   if (rst_i)
   if (rst_i)
   begin
   begin
        r_last_opcode   <= 32'b0;
            r_opcode        <= 32'b0;
        r_last_pc       <= 32'b0;
            r_opcode_pc     <= 32'b0;
        r_last_valid    <= 1'b0;
            r_opcode_valid  <= 1'b0;
 
            r_branch        <= 1'b0;
   end
   end
   else
   else
   begin
   begin
        // Record last valid instruction passed to exec stage
            r_branch        <= branch_i;
        if (!stall_i | !data_valid_i)
 
 
            if (~stall_i)
        begin
        begin
            r_last_pc        <= opcode_pc_o;
                r_opcode_pc     <= d_pc;
            r_last_opcode    <= opcode_o;
                r_opcode        <= data_i;
            r_last_valid     <= opcode_valid_o;
                r_opcode_valid  <= (data_valid_i & !branch_i);
        end
        end
   end
   end
end
end
 
 
 
    // Opcode output
 
    assign opcode_valid_o  = r_opcode_valid & ~branch_i & ~r_branch;
 
    assign opcode_o        = r_opcode;
 
    assign opcode_pc_o     = r_opcode_pc;
 
end
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Assignments
// Opcode output
//-------------------------------------------------------------------
//-------------------------------------------------------------------
 
else
// Instruction Fetch
begin : NO_FETCH_FLOPS
assign pc_o            = stall_i ? d_pc : (branch_i ? branch_pc_i : (~data_valid_i ? d_pc : r_pc));
 
assign fetch_o         = branch_i ? 1'b1 : r_rd;
 
 
 
// Opcode output
// Opcode output
assign opcode_valid_o  = stall_i ? r_last_valid : (data_valid_i & !branch_i);
    assign opcode_valid_o  = (data_valid_i & !branch_i);
assign opcode_o        = stall_i ? r_last_opcode : (opcode_valid_o ? data_i : 32'b0);
    assign opcode_o        = data_i;
assign opcode_pc_o     = stall_i ? r_last_pc : (opcode_valid_o ? d_pc : 32'b0);
    assign opcode_pc_o     = d_pc;
 
end
 
endgenerate
 
 
 
//-------------------------------------------------------------------
 
// Opcode output
 
//-------------------------------------------------------------------
// If simulation, RA = 03 if NOP instruction
// If simulation, RA = 03 if NOP instruction
`ifdef SIMULATION
`ifdef SIMULATION
    wire [7:0] v_fetch_inst = {2'b00, opcode_o[31:26]};
    wire [7:0] v_fetch_inst = {2'b00, opcode_o[31:26]};
    wire       v_is_nop     = (v_fetch_inst == `INST_OR32_NOP);
    wire       v_is_nop     = (v_fetch_inst == `INST_OR32_NOP);
    assign     ra_o         = v_is_nop ? 5'd3 : opcode_o[20:16];
    assign     ra_o         = v_is_nop ? 5'd3 : opcode_o[20:16];

powered by: WebSVN 2.1.0

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