Memories

 

This page describes the included Memory components. Memory is only useful if you can set its initial value, and that's not a trivial task. We wrote a script that make this process tractable, though not yet easy or enjoyable. Get this script here.

Module: ROM256x32

    In our single-cycle designs we don't need to write to the instruction memory, so this ROM allows us to write a program with up to 256 instructions. If the need for larger programs arises they can be tacked together, but that will make initializing the memory more complex. The actual implementation depends on the ovi_unisim library. 

    This component actually consists of 32 256x1 bit ROMs, 1 for each bit in the instruction. Each ROM has its own internal INIT parameter, and we have provided parameters INIT_C0 through INIT_C31 which are 256 bit hex values that init an entire ROM bit-slice.

     Setting the ROM requires updating all of the INIT_C0 - INIT_C31 parameters appropriately. To make this possible we've written a script that takes an input in MIPS assembly and outputs the proper values for the individual INIT_Cn values.

 

Parameters:

 
Name Default Description
INIT_C0 256'h0 initial value for bit 0 of all 256 words
..... .... .....
INIT_C31 256'h0 initial value for bit 31 of all 256 words
 

Port Description:

 
Name Dir Width Description
ADDR In 8 Address to read from
OUTPUT OUT 31 Word stored at Address ADDR
 

Symbol:

 

 

Notes:

 
  1. There must be a glbl.GSR signal defined to use this component

Initializing:

 
Here's an example of initializing a ROM using the script asm_to_hex.pl.  The program is stored in simple.s and we'll be generating temporary file simple.rom.  The last piece of information we need is that hierarchical name of the ROM. I'll assume that the instance of the ROM is named "IROM". 
  1. If you haven't already, downloaded the script asm_to_hex.pl and add it to your design.
  2. Type the follow command into the Active-HDL console:
    > runscript asm_to_hex.pl -in=simple.s -out=simple.rom -init=ROM -obj=MemorySystem.BIOS.U1_ARRAY%d.INIT
  3. Now simple.rom looks like this:
    defparam
        IROM.INIT_C0 = 256'h000...
        ....
        IROM.INIT_C31 = 256'h000...
  4. If IROM is declared in a Verilog file, skip to step 6
  5. Add a module declarations block to your block diagram (See Active-HDL Help)
  6. add the following line to the module declarations block:
    `include "simple.rom"

Module: Ram256x32_sw_ar_wb

    This is the data memory you should use for Lab1. The reason is that it supports asynchronous reads (output changes when address changes).  This memory has only 256 words.  This means that only the lower 10 bits of your Address will be used.  It supports writing at the byte, half-word, and word level.  This is specified by the value of WE (2'b00 = don't write, 2'b01 = write bits [7:0] into correct byte, 2'10 = write word, 2'b11 = write half-word to upper or lower half.

Parameters:

 
Name Default Description
INIT 36'h0 The initial output value
SRVAL 36'h0 The output value when SSR is set
INIT_00-1F 256'h0 Initialization values. Not USED
 

Port Description:

 
Name Dir Width Description
CLK In 1 clock signal 
ADDR In 10 ADDR to read or write
DI In 32 Data to write
WE In 2 write signals: 2'b01 = write byte , 2'b10 = write word, 2'b11 = write half-word
DO Out 32 Data read from memory
 

Symbol:

 

 

Notes:

 
  1. There must be a glbl.GSR signal defined to use this component

Initializing:

 
Here's an example of initializing a RAM using the script asm_to_hex.pl.  The data is stored in simple.hex and we'll be generating temporary file simple.ram.  The last piece of information we need is that hierarchical name of the RAM. I'll assume that the instance of the RAM is named "DRAM". 
  1. If you haven't already, downloaded the script asm_to_hex.pl and add it to your design.
  2. Type the follow command into the Active-HDL console:
    > runscript asm_to_hex.pl -in=simple.hex -out=simple.ram -init=ASYNC -obj=DRAM
  3. Now simple.ram looks like this:
    defparam
        DRAM.Byte0.U1.INIT_00 = 32'h000...
        ....
        DRAM.Byte3.U8.INIT_07 = 32'h000...
  4. If DRAM is declared in a Verilog file, skip to step 6
  5. Add a module declarations block to your block diagram (See Active-HDL Help)
  6. Add the following code to your declarations block:
    //synopsys translate_off
    `include "simple.ram"
    //synopsys translate_on

Module: ram_control

    This is a small combinational block that controls byte-level writes in the memory unit we designed. Basically, our memory consists of 4 banks that are each 1 byte wide. For SW, we simply hit all 4 with a WE. However, for SB we only want to write to a single byte, and leave the others unchanged. The ram_control unit makes sure this all happens correctly. 

Parameters:

  NONE
 

Port Description:

 
Name Dir Width Description
ADDR In 2 bottom bits of address specify the byte to write
WB In 1 signals an SB instruction
WW In 1 signals an SW instruction
B_WE Out 3 the WE signals for the individual memory banks
 

Symbol:

 

 

Notes:

 
  1. This only supports SW and SB.  If you really need SH, ask for help

Module: ramb16_s36_wb

    This data memory component consists of 4 blockram elements configured as byte-wide units. This means that there are 2048 words of memory, for a total of 8KB.  To enable byte-level writes we use the ram_control unit described above.  These blockram units have synchronous write, and can be initialized. 

    NOTE:  At release, we can only init the first 64 words of memory. We'll have a better solution out soon 

Parameters:

 
Name Default Description
INIT 36'h0 The initial output value
SRVAL 36'h0 The output value when SSR is set
WRITE_MODE "WF" determines relationship between inputs and outputs
INIT_00-3F 256'h0 Initialization values. Only INIT_00-07 work NOW
 

Port Description:

 
Name Dir Width Description
EN In 1 make the memory accessible
CLK In 1 clock signal 
SSR In 1 synchronous static reset
ADDR In 13 ADDR to read or write
DI In 32 Data to write
DIP In 4 parity of input data (ignored)
WE In 2 write signals: WE[0] = WB, WE[1] = WW
DO Out 32 Data read from memory
DOP Out 4 parity of output data (ignored)
 

Symbol:

 

 

Notes:

 
  1. There must be a glbl.GSR signal defined to use this component

Initializing:

 
Here's an example of initializing a RAM using the script asm_to_hex.pl.  The data is stored in simple.hex and we'll be generating temporary file simple.ram.  The last piece of information we need is that hierarchical name of the RAM. I'll assume that the instance of the RAM is named "DRAM". 
  1. If you haven't already, downloaded the script asm_to_hex.pl and add it to your design.
  2. Type the follow command into the Active-HDL console:
    > runscript asm_to_hex.pl -in=simple.hex -out=simple.ram -init=RAM \ -obj=DRAM.INIT_%x
  3. Now simple.ram looks like this:
    defparam
        DRAM.INIT_00 = 256'h000...
        ....
        DRAM.INIT_3F = 256'h000...
  4. If DRAM is declared in a Verilog file, skip to step 6
  5. Add a module declarations block to your block diagram (See Active-HDL Help)
  6. Copy contents of simple.rom into the file where DRAM is defined.
  7. Remove old values for DRAM.INIT_0x

Module: Memory_Toplevel

    This module contains the entire memory system for the processor that you will be building. It contains a ROM that acts as the BIOS, three asynchronous RAMs that act as Instruction Memory, Data Memory and stack space, and an IO controller that routes signals to and from the various IO devices on the processor. This module manages both instruction and data memory and fetches the appropriate instructions and data based on the addresses provided to it.

Memory space is mapped as follows:

 

Port Description:

 
Name Dir Width Description
CLK In 1 clock signal 
WE In 2 write signals: WE[0] = WB, WE[1] = WW
InstAddress In 32 The address of the instruction that should be fetched
Data Address In 32 The address to read/write data to
IODev1Input In 32 Data in from IO Device 1
IODev2Input In 32 Data in from IO Device 2
IODev3Input In 32 Data in from IO Device 3
IODev4Input In 32 Data in from IO Device 4
DataOut Out 32 Data read from memory
Instruction Out 32 Instruction read from memory
IODev1WE Out 2 WriteEnable signal for IO Device 1
IODev2WE Out 2 WriteEnable signal for IO Device 2
IODev3WE Out 2 WriteEnable signal for IO Device 3
IODev4WE Out 2 WriteEnable signal for IO Device 4
 

Symbol:

 

 

Module: MMU

    This module acts as the memory management unit for the memory system on the processor. It routes WE signals and data to the various memory modules and I/O Controller based on the address given to it. It follows the same address conventions as Memory_Toplevel and is a part of it.

 

Port Description:

 
Name Dir Width Description
writeEnable In 2 write signals: writeEnable[0] = WB, writeEnable[1] = WW
InstructionAddress In 32 The address of the instruction that should be fetched
Data Address In 32 The address to read/write data to
ROMAddress Out 8 The address to access in the ROM
InstAddress Out 10 The address to access in the IRAM
StackAddress Out 10 The address to access in the Stack
DataAddress Out 10 The address to access in DRAM
IOAddress Out 10 The address to access for the I/O Controller
InstWE Out 2 WriteEnable signal for IRAM
DataWE Out 2 WriteEnable signal for DRAM
StackWE Out 2 WriteEnable signal for Stack
IOWE Out 2 WriteEnable signal for the I/O Controller
instFromROM Out 1 Signal to a mux to indicate if the instruction source is the BIOS or IRAM
dataTarget Out 2 Signal to a mux to indicate if the data is coming from the IRAM, DRAM, Stack or I/O Controller
 

Symbol:

 

None