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

Subversion Repositories altor32

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

Show entire file | Details | Blame | View Log

Rev 36 Rev 37
Line 8... Line 8...
//               Email: admin@ultra-embedded.com
//               Email: admin@ultra-embedded.com
//
//
//                       License: LGPL
//                       License: LGPL
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
//
// This source file may be used and distributed without         
// This source file may be used and distributed without         
// restriction provided that this copyright statement is not    
// restriction provided that this copyright statement is not    
// removed from the file and that any derivative work contains  
// removed from the file and that any derivative work contains  
// the original copyright notice and the associated disclaimer. 
// the original copyright notice and the associated disclaimer. 
Line 79... Line 79...
parameter           PIPELINED_FETCH         = "DISABLED";
parameter           PIPELINED_FETCH         = "DISABLED";
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Registers
// Registers
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg         r_rd;
reg         rd_q;
reg [31:0]  r_pc;
reg [31:0]  pc_q;
reg [31:0]  d_pc;
reg [31:0]  pc_last_q;
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Next PC state machine
// Next PC state machine
//-------------------------------------------------------------------
//-------------------------------------------------------------------
wire [31:0] next_pc = r_pc + 32'd4;
wire [31:0] next_pc_w = pc_q + 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;
        pc_q        <= BOOT_VECTOR + `VECTOR_RESET;
        d_pc        <= BOOT_VECTOR + `VECTOR_RESET;
        pc_last_q   <= BOOT_VECTOR + `VECTOR_RESET;
        r_rd        <= 1'b1;
        rd_q        <= 1'b1;
   end
   end
   else if (~stall_i)
   else if (~stall_i)
   begin
   begin
        r_rd        <= 1'b0;
 
        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;
            rd_q        <= 1'b0;
 
            pc_last_q   <= pc_o;
 
            pc_q        <= branch_pc_i + 4;
        end
        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
            // New cache line?
            // New cache line?
            if (next_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
            if (next_pc_w[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
            begin
                rd_q    <= 1'b1;
                // Start fetch of next line
            else
                r_rd  <= 1'b1;
                rd_q    <= 1'b0;
            end
 
 
 
            r_pc <= next_pc;
            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
   end
end
end
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Assignments
 
//-------------------------------------------------------------------
 
 
 
// Instruction Fetch
// Instruction Fetch
 
//-------------------------------------------------------------------
always @ *
always @ *
begin
begin
    // Stall, revert to last requested PC
    // Stall, revert to last requested PC
    if (stall_i)
    if (stall_i)
        pc_o = d_pc;
        pc_o    = pc_last_q;
    else if (branch_i)
    else if (branch_i)
        pc_o = branch_pc_i;
        pc_o = branch_pc_i;
    else if (~data_valid_i)
    else if (~data_valid_i)
        pc_o = d_pc;
        pc_o    = pc_last_q;
    else
    else
        pc_o = r_pc;
        pc_o    = pc_q;
end
end
 
 
assign fetch_o         = branch_i ? 1'b1 : r_rd;
assign fetch_o  = branch_i ? 1'b1 : rd_q;
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Opcode output (retiming)
// Opcode output (retiming)
//-------------------------------------------------------------------
//-------------------------------------------------------------------
generate
generate
if (PIPELINED_FETCH == "ENABLED")
if (PIPELINED_FETCH == "ENABLED")
begin: FETCH_FLOPS
begin: FETCH_FLOPS
    reg [31:0] r_opcode;
    reg [31:0] opcode_q;
    reg [31:0] r_opcode_pc;
    reg [31:0] opcode_pc_q;
    reg        r_opcode_valid;
    reg        opcode_valid_q;
    reg        r_branch;
    reg        branch_q;
 
 
    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_opcode        <= 32'b0;
            opcode_q        <= 32'b0;
            r_opcode_pc     <= 32'b0;
            opcode_pc_q     <= 32'b0;
            r_opcode_valid  <= 1'b0;
            opcode_valid_q  <= 1'b0;
            r_branch        <= 1'b0;
            branch_q        <= 1'b0;
       end
       end
       else
       else
       begin
       begin
            r_branch        <= branch_i;
            branch_q        <= branch_i;
 
 
            if (~stall_i)
            if (~stall_i)
            begin
            begin
                r_opcode_pc     <= d_pc;
                opcode_pc_q     <= pc_last_q;
                r_opcode        <= data_i;
                opcode_q        <= data_i;
                r_opcode_valid  <= (data_valid_i & !branch_i);
                opcode_valid_q  <= (data_valid_i & !branch_i);
            end
            end
       end
       end
    end
    end
 
 
    // Opcode output
    // Opcode output
    assign opcode_valid_o  = r_opcode_valid & ~branch_i & ~r_branch;
    assign opcode_valid_o  = opcode_valid_q & ~branch_i & ~branch_q;
    assign opcode_o        = r_opcode;
    assign opcode_o        = opcode_q;
    assign opcode_pc_o     = r_opcode_pc;
    assign opcode_pc_o     = opcode_pc_q;
end
end
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Opcode output
// Opcode output
//-------------------------------------------------------------------
//-------------------------------------------------------------------
else
else
begin : NO_FETCH_FLOPS
begin : NO_FETCH_FLOPS
    // Opcode output
 
    assign opcode_valid_o  = (data_valid_i & !branch_i);
    assign opcode_valid_o  = (data_valid_i & !branch_i);
    assign opcode_o        = data_i;
    assign opcode_o        = data_i;
    assign opcode_pc_o     = d_pc;
    assign opcode_pc_o     = pc_last_q;
end
end
endgenerate
endgenerate
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Opcode output
// 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] fetch_inst_w = {2'b00, opcode_o[31:26]};
    wire       v_is_nop     = (v_fetch_inst == `INST_OR32_NOP);
    wire       nop_inst_w   = (fetch_inst_w == `INST_OR32_NOP);
    assign     ra_o         = v_is_nop ? 5'd3 : opcode_o[20:16];
    assign     ra_o         = nop_inst_w ? 5'd3 : opcode_o[20:16];
`else
`else
    assign     ra_o         = opcode_o[20:16];
    assign     ra_o         = opcode_o[20:16];
`endif
`endif
 
 
assign rb_o            = opcode_o[15:11];
assign rb_o            = opcode_o[15:11];

powered by: WebSVN 2.1.0

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