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
[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [new_lm32/] [rtl/] [lm32_itlb.v] - Rev 48
Compare with Previous | Blame | View Log
/* * LatticeMico32 * Instruction Translation Lookaside Buffer * * Copyright (c) 2011-2012 Yann Sionneau <yann.sionneau@gmail.com> * Copyright (c) 2012 Michael Walle <michael@walle.cc> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ `include "lm32_include.v" `ifdef CFG_MMU_ENABLED `define LM32_ITLB_CTRL_FLUSH 5'h1 `define LM32_ITLB_CTRL_UPDATE 5'h2 `define LM32_TLB_CTRL_INVALIDATE_ENTRY 5'h10 `define LM32_ITLB_STATE_RNG 1:0 `define LM32_ITLB_STATE_CHECK 2'b01 `define LM32_ITLB_STATE_FLUSH 2'b10 `define LM32_ITLB_OFFSET_RNG offset_msb:offset_lsb `define LM32_ITLB_IDX_RNG index_msb:index_lsb `define LM32_ITLB_VPFN_RNG vpfn_msb:vpfn_lsb `define LM32_ITLB_TAG_RNG tag_msb:tag_lsb `define LM32_ITLB_ADDR_RNG (index_width-1):0 `define LM32_ITLB_DATA_WIDTH (vpfn_width+tag_width+1) `define LM32_ITLB_DATA_RNG (`LM32_ITLB_DATA_WIDTH-1):0 ///////////////////////////////////////////////////// // Module interface ///////////////////////////////////////////////////// module lm32_itlb ( // ----- Inputs ------- clk_i, rst_i, enable, stall_a, stall_f, stall_d, stall_x, pc_a, pc_f, pc_x, read_enable_f, tlbpaddr, tlbvaddr, update, flush, invalidate, // ----- Outputs ------- physical_pc_f, stall_request, miss_vfn, miss_f, miss_x ); ///////////////////////////////////////////////////// // Parameters ///////////////////////////////////////////////////// parameter entries = 1024; // Number of entires in ITLB parameter page_size = 4096; // ITLB page size localparam offset_width = (`CLOG2(page_size)-2); localparam index_width = `CLOG2(entries); localparam offset_lsb = 2; localparam offset_msb = (offset_lsb+offset_width-1); localparam index_lsb = (offset_msb+1); localparam index_msb = (index_lsb+index_width-1); localparam tag_lsb = (index_msb+1); localparam tag_msb = (`LM32_WORD_WIDTH-1); localparam tag_width = (tag_msb-tag_lsb+1); localparam vpfn_lsb = (offset_msb+1); localparam vpfn_msb = (`LM32_WORD_WIDTH-1); localparam vpfn_width = (vpfn_msb-vpfn_lsb+1); ///////////////////////////////////////////////////// // Inputs ///////////////////////////////////////////////////// input clk_i; // Clock input rst_i; // Reset input enable; // Instruction TLB enable input stall_a; // Stall instruction in A stage input stall_f; // Stall instruction in F stage input stall_d; // Stall instruction in D stage input stall_x; // Stall instruction in X stage input [`LM32_PC_RNG] pc_a; // Address of instruction in A stage input [`LM32_PC_RNG] pc_f; // Address of instruction in F stage input [`LM32_PC_RNG] pc_x; // Address of instruction in X stage input read_enable_f; // Indicates if cache access is valid input [`LM32_WORD_RNG] tlbpaddr; input [`LM32_WORD_RNG] tlbvaddr; input update; input flush; input invalidate; ///////////////////////////////////////////////////// // Outputs ///////////////////////////////////////////////////// output [`LM32_PC_RNG] physical_pc_f; reg [`LM32_PC_RNG] physical_pc_f; output stall_request; wire stall_request; output [`LM32_WORD_RNG] miss_vfn; wire [`LM32_WORD_RNG] miss_vfn; output miss_f; wire miss_f; output miss_x; reg miss_x; ///////////////////////////////////////////////////// // Internal nets and registers ///////////////////////////////////////////////////// wire [`LM32_ITLB_ADDR_RNG] read_address; wire [`LM32_ITLB_ADDR_RNG] write_address; wire read_port_enable; wire write_port_enable; wire [`LM32_ITLB_DATA_RNG] write_data; reg [`LM32_ITLB_STATE_RNG] state; reg [`LM32_ITLB_ADDR_RNG] flush_set; wire [`LM32_ITLB_TAG_RNG] tlbe_tag_f; wire [`LM32_ITLB_VPFN_RNG] tlbe_pfn_f; wire tlbe_valid_f; reg miss_d; wire flushing; ///////////////////////////////////////////////////// // Functions ///////////////////////////////////////////////////// //////////////////////////////////////////////////// // Instantiations ///////////////////////////////////////////////////// lm32_ram #( // ----- Parameters ------- .data_width (`LM32_ITLB_DATA_WIDTH), .address_width (index_width) // Modified for Milkymist: removed non-portable RAM parameters ) data_ram ( // ----- Inputs ------- .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), .read_address (read_address), .enable_read (read_port_enable), .write_address (write_address), .enable_write (`TRUE), .write_enable (write_port_enable), .write_data (write_data), // ----- Outputs ------- .read_data ({tlbe_pfn_f, tlbe_tag_f, tlbe_valid_f}) ); ///////////////////////////////////////////////////// // Combinational logic ///////////////////////////////////////////////////// // Compute address to use to index into the ITLB memory assign read_address = pc_a[`LM32_ITLB_IDX_RNG]; assign write_address = (flushing == `TRUE) ? flush_set : tlbvaddr[`LM32_ITLB_IDX_RNG]; assign read_port_enable = (stall_a == `FALSE); assign write_port_enable = (update == `TRUE) || (invalidate == `TRUE) || (flushing == `TRUE); assign write_data = ((invalidate == `TRUE) || (flushing == `TRUE)) ? {{`LM32_ITLB_DATA_WIDTH-1{1'b0}}, `FALSE} : {tlbpaddr[`LM32_ITLB_VPFN_RNG], tlbvaddr[`LM32_ITLB_TAG_RNG], `TRUE}; assign tlbe_match_f = ({tlbe_tag_f, tlbe_valid_f} == {pc_f[`LM32_ITLB_TAG_RNG], `TRUE}); assign miss_vfn = {pc_x[`LM32_ITLB_VPFN_RNG], {offset_width{1'b0}}, 2'b0}; assign miss_f = (enable == `TRUE) && (tlbe_match_f == `FALSE) && (stall_f == `FALSE); assign flushing = state[1]; assign stall_request = (flushing == `TRUE); always @(*) begin if (enable == `TRUE) begin if (tlbe_match_f == `TRUE) physical_pc_f = {tlbe_pfn_f, pc_f[`LM32_ITLB_OFFSET_RNG]}; else physical_pc_f = {`LM32_PC_WIDTH{1'b0}}; end else physical_pc_f = pc_f; end ///////////////////////////////////////////////////// // Sequential logic ///////////////////////////////////////////////////// always @(posedge clk_i `CFG_RESET_SENSITIVITY) begin if (rst_i == `TRUE) begin miss_d <= `FALSE; miss_x <= `FALSE; end else begin if (stall_d == `FALSE) miss_d <= miss_f; if (stall_x == `FALSE) miss_x <= miss_d; end end always @(posedge clk_i `CFG_RESET_SENSITIVITY) begin if (rst_i == `TRUE) begin flush_set <= {index_width{1'b1}}; state <= `LM32_ITLB_STATE_FLUSH; end else begin case (state) `LM32_ITLB_STATE_CHECK: begin if (flush == `TRUE) begin flush_set <= {index_width{1'b1}}; state <= `LM32_ITLB_STATE_FLUSH; end end `LM32_ITLB_STATE_FLUSH: begin if (flush_set == {index_width{1'b0}}) state <= `LM32_ITLB_STATE_CHECK; flush_set <= flush_set - 1'b1; end endcase end end endmodule `endif