URL
https://opencores.org/ocsvn/altor32/altor32/trunk
Subversion Repositories altor32
[/] [altor32/] [trunk/] [rtl/] [cpu/] [altor32_fetch.v] - Rev 36
Go to most recent revision | Compare with Previous | Blame | View Log
//----------------------------------------------------------------- // AltOR32 // Alternative Lightweight OpenRisc // V2.1 // Ultra-Embedded.com // Copyright 2011 - 2014 // // Email: admin@ultra-embedded.com // // License: LGPL //----------------------------------------------------------------- // // Copyright (C) 2011 - 2013 Ultra-Embedded.com // // This source file may be used and distributed without // restriction provided that this copyright statement is not // removed from the file and that any derivative work contains // the original copyright notice and the associated disclaimer. // // This source file is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General // Public License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any // later version. // // This source is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the GNU Lesser General Public License for more // details. // // You should have received a copy of the GNU Lesser General // Public License along with this source; if not, write to the // Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA //----------------------------------------------------------------- //----------------------------------------------------------------- // Includes //----------------------------------------------------------------- `include "altor32_defs.v" //----------------------------------------------------------------- // Module - 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 r_rd; reg [31:0] r_pc; reg [31:0] d_pc; //------------------------------------------------------------------- // Next PC state machine //------------------------------------------------------------------- wire [31:0] next_pc = r_pc + 32'd4; always @ (posedge clk_i or posedge rst_i) begin if (rst_i) begin r_pc <= BOOT_VECTOR + `VECTOR_RESET; d_pc <= BOOT_VECTOR + `VECTOR_RESET; r_rd <= 1'b1; end else if (~stall_i) begin r_rd <= 1'b0; d_pc <= pc_o; // Branch - Next PC = branch target + 4 if (branch_i) begin r_pc <= branch_pc_i + 4; end // Normal sequential execution (and instruction is ready) else if (data_valid_i) begin // New cache line? if (next_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}}) begin // Start fetch of next line r_rd <= 1'b1; end r_pc <= next_pc; end end end //------------------------------------------------------------------- // 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) begin if (rst_i) begin r_opcode <= 32'b0; r_opcode_pc <= 32'b0; r_opcode_valid <= 1'b0; r_branch <= 1'b0; end else begin r_branch <= branch_i; if (~stall_i) begin r_opcode_pc <= d_pc; r_opcode <= data_i; r_opcode_valid <= (data_valid_i & !branch_i); 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 //------------------------------------------------------------------- // Opcode output //------------------------------------------------------------------- else begin : NO_FETCH_FLOPS // Opcode output assign opcode_valid_o = (data_valid_i & !branch_i); assign opcode_o = data_i; assign opcode_pc_o = d_pc; end endgenerate //------------------------------------------------------------------- // Opcode output //------------------------------------------------------------------- // If simulation, RA = 03 if NOP instruction `ifdef SIMULATION wire [7:0] v_fetch_inst = {2'b00, opcode_o[31:26]}; wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP); assign ra_o = v_is_nop ? 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
Go to most recent revision | Compare with Previous | Blame | View Log