⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory_sizer_dual_path.v

📁 硬件方面的源代码-有关IP核的
💻 V
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------------------------------// Wishbone memory_sizer_dual_path core//// This file is part of the "memory_sizer" project.// http://www.opencores.org/cores/memory_sizer// //// Description: See description below (which suffices for IP core//                                     specification document.)//// Copyright (C) 2001 John Clayton and OPENCORES.ORG//// 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, download it from http://www.opencores.org/lgpl.shtml////----------------------------------------------------------------------------//// Author: John Clayton// Date  : November  5, 2001// Update: 11/05/01 copied this file from rs232_syscon.v (pared down).// Update: 11/16/01 Continued coding efforts.  Redesigned logic with scalable//                  "byte sized barrel shifter" and byte reversal blocks (byte//                  reversal is implemented as a function "byte_reversal").//                  Changed encoding of memory_width_i and access_width_i.//                  Implemented new counting and byte enable logic.// Update: 12/04/01 Realized there was a mistake in the byte enable logic.//                  Fixed it by using dat_shift to shift the byte enables.//                  Made "byte_enable_source" twice as wide.// Update: 12/05/01 Eliminated the "count" in favor of using "dat_shift" along//                  with new terminal_count logic, in order to fix flaws found//                  in the terminal_count signal.  Fixed byte steering for//                  stores.  Tested using N_PP = 4, and LOG2_N_PP = 2 and saw//                  correct operation for all sizes of store operations.// Update: 12/13/01 Began testing with read logic.  Found byte enable problem//                  during writes.  Removed "byte_dirty" bits.// Update: 12/14/01 Added "latch_be_source" to create byte enables for reading//                  which are based on the size of the memory (which fixed a//                  bug in reading.)  The module appears to be fully working,//                  except for "big_endian" reads.// Update: 12/17/01 Introduced the "middle_bus" in order to decouple the//                  byte reverser from the byte steering logic, so that for//                  writes byte reversing is done first, but for reads then//                  byte reversing is done last.  Introduced "latch_be_adjust"//                  to cover big endian reads -- all is now working.// Update: 12/17/01 Removed "middle_bus" (the two units are still decoupled!)//                  because it seemed unnecessary.  This freed up Tbuffs, but//                  had no effect on resource utilization (slices).  Also, the//                  maximum reported clock speed increased.  Removed debug//                  port.// Update: 12/18/01 Copied this from "memory_sizer_tristate_switching.v"//                  This file will now have duplicate byte steering and byte//                  swapping logic.  Changed module name to //                  "memory_sizer_dual_path"//// Description//-------------------------------------------------------------------------------------//// This module is just like "memory_sizer" except that it provides separate// paths for the writing and the reading of memory.  By avoiding the tri-state// bus switching, it uses less tri-state buffers, and should operate faster// than the original "memory_sizer"//// ORIGINAL DESCRIPTION:// This logic module takes care of sizing bus transfers between a small// microprocessor and its memory.  It enables the microprocessor to// generate access requests for different widths (read/write BYTE, WORD and// DWORD, etc.) using memory which is sized independently of the accesses.//// Thus, a 32-bit microprocessor using 32-bit wide accesses can use this block// in order to boot from an 8-bit wide flash device.  This block takes care of // generating the four 8-bit memory cycles that are required in order to read// each DWORD for alimentation of the microprocessor.//// Also, if the memory supports byte enables during a write cycle, then this// block "steers" a smaller data word to the appropriate location within a// larger memory word, and activates the appropriate byte enables so that only// the BYTEs which are affected by the write cycle are actually overwritten.//// Moreover, the memory_sizer block takes care of translating little-endian// formats into big-endian formats and vice-versa.  This is accomplished by the// use of a single input bit "endianness_i"//// The memory_sizer block does not latch or store the parameters which it uses// for operation.  The input signals determine its operation on an ongoing// basis.  In fact, the only data storage present in this block is the latching// provided for data which must be held during multiple cycle read operations.// (There are also some counters, which don't count as data storage...)//// Encoding for access_width_i and memory_width_i is as follows://// Bits           Significance// ------         ------------// 0001            8-bits wide (1 byte)// 0010           16-bits wide (2 bytes)// 0100           32-bits wide (4 bytes)// 1000           64-bits wide (8 bytes)//// (The access_width_i and memory_width_i inputs are sized according to the// parameter LOG2_N_PP, but the significance is the same, using whatever// lsbs are present.)//// It is envisioned that a designer may include this block for flexibility.// If all of the memory accesses are of a single width, and the memory matches// that width, and there is no need for endianness translation, then the user// could hard-code the "memory_width_i" and "access_width_i" to correspond// to the same width, hard-code the "endianness_i" input to the desired value// and then the memory_sizer block would effectively do nothing, or very little.// Most of its size and resources would be optimized out of the design at// compile time.  The dat_shift counter and read-storage latches would not be// used, and so they would not even be synthesized.//// On the other hand, if the memory in the SOC (system on a chip) comprises// various width devices, then the decode logic which selects the blocks of// memory is ORed (for each like-sized block) and then concatenated in the// proper order to generate a dynamic "mem_width_i" signal to the// memory_sizer, so that the different size accesses are accomodated.  The// processor side, meanwhile (being "access_width_i"), could still be// hard-wired to a given width, or be connected so that different width loads// and stores are generated as needed.//// This block may generate exceptions to the processor, in the case of a write// request, for example, to store a BYTE into a DWORD wide memory which doesn't// support the use of byte enables.  Although this could be done by reading the// wider memory and masking in the correct BYTE, followed by storing the// results back into the memory, this was deemed too complex a task for this// block.  Responsibility for such operations, if desired, would devolve upon// the microprocessor itself.  Support of byte enables is indicated by a "1" on// the "memory_has_be_i" line.//// The clock used by memory_sizer is not limited to the speed of the clock used// by the microprocessor.  Since the memory_sizer contains only combinational// logic, simple counters and some possible latches, it might run much faster// than the microprocessor.  In that case, generate two clocks which are// synchronous:  one for the processor, and another for memory_sizer.// The memory_sizer clock could be 2x, 4x or even 8x that of the processor.// In this way, the memory_sizer block can complete multiple memory read cycles// in the same time as a single processor cycle -- assuming the memory is fast// enough to support it -- and thereby the memory latency can be reduced.//// The memory_sizer block is not responsible for implementing wait states for// the memory, especially since the number of wait states required can vary// for each type and width of memory used.  Instead, there is an "access_ack_o"// signal to indicate completion of the entire requested memory access to the// processor.  On the memory side, there is "memory_ack_i" used to indicate to// the memory_sizer block that the memory has completed the current cycle in// progress.  Therefore, in order to implement wait states, the memory sytem// address decoder logic should generate the "memory_ack_i" signal based on the// different types of memory present within the system, which can also be// programmable.  A parameterized watchdog timer inside of the memory sizer block// indicates when "memory_ack_i" has not been asserted in a reasonable number// of clock cycles.  When this occurs, an exception is raised.  The timer// is started when "sel_i" is active (high).  sel_i must remain active// until the access is completed, otherwise the timer will reset and the// access is aborted.  If you don't want to use the watchdog portion of this// block then simply don't connect the exception_watchdog_o line, and the watchdog// timer will be optimized out of the logic.//// If desired, registers can be placed on the memory side of the block.  They// are treated just like memory of a given width, although access requests for// misaligned writes, or writes which are smaller than the size of the registers,// should generate exceptions, unless the registers support byte enables.//// Addresses are always assumed to be byte addresses in this unit, since the// smallest granularity of data used in it is the BYTE.  Also, the data bus// size used must be a multiple of 8 bits, for the same reason.////-------------------------------------------------------------------------------------`define BYTE_SIZE  8         // Number of bits in one bytemodule memory_sizer_dual_path (  clk_i,  reset_i,  sel_i,  memory_ack_i,  memory_has_be_i,  memory_width_i,  access_width_i,  access_big_endian_i,  adr_i,  we_i,  dat_io,  memory_dat_io,  memory_adr_o,              // Same width as adr_i (only lsbs are modified)  memory_we_o,  memory_be_o,  access_ack_o,  exception_be_o,  exception_watchdog_o  );// Parameters// The timer value can be from [0 to (2^WATCHDOG_TIMER_BITS_PP)-1] inclusive.parameter N_PP                    = 4;   // number of bytes in data busparameter LOG2_N_PP               = 2;   // log base 2 of data bus size (bytes)parameter ADR_BITS_PP             = 32;  // # of bits in adr busesparameter WATCHDOG_TIMER_VALUE_PP = 12;  // # of sys_clks before ack expectedparameter WATCHDOG_TIMER_BITS_PP  = 4;   // # of bits needed for timer// I/O declarationsinput clk_i;           // Memory sub-system clock inputinput reset_i;         // Reset signal for this moduleinput sel_i;           // Enables watchdog timer, activates memory_sizerinput memory_ack_i;    // Ack from memory (delay for wait states)input memory_has_be_i; // Indicates memory at current address has byte enablesinput [LOG2_N_PP:0] memory_width_i;        // Width code of memoryinput [LOG2_N_PP:0] access_width_i;        // Width code of access requestinput access_big_endian_i;                 // 0=little endian, 1=big endianinput [ADR_BITS_PP-1:0] adr_i;             // Address bus inputinput we_i;                                // type of accessinout [`BYTE_SIZE*N_PP-1:0] dat_io;        // processor data businout [`BYTE_SIZE*N_PP-1:0] memory_dat_io; // data bus to memoryoutput [ADR_BITS_PP-1:0] memory_adr_o;     // address bus to memoryoutput memory_we_o;                        // we to memoryoutput [N_PP-1:0] memory_be_o;             // byte enables to memoryoutput access_ack_o;         // shows that access is completedoutput exception_be_o;       // exception for write to non-byte-enabled memoryoutput exception_watchdog_o; // exception for memory_ack_i watch dog timeout

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -