Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
114
Добавлен:
26.03.2016
Размер:
7.4 Mб
Скачать

12.8 Memory Synthesis

There are several approaches to memory synthesis:

1.Random logic using flip-flops or latches

2.Register files in datapaths

3.RAM standard components

4.RAM compilers

The first approach uses large vectors or arrays in the HDL code. The synthesizer will map these elements to arrays of flip-flops or latches depending on how the timing of the assignments is handled. This approach is independent of any software or type of ASIC and is the easiest to use but inefficient in terms of area. A flip-flop may take up 10 to 20 times the area of a six-transistor static RAM cell.

The second approach uses a synthesis directive or hand instantiation to synthesize a memory to a datapath component. Usually the datapath components are constructed from latches in a regular array. These are slightly more efficient than a random arrangement of logic cells, but the way we create the memory then depends on the software and the ASIC technology we are using.

The third approach uses standard components supplied by an ASIC vendor. For example, we can instantiate a small RAM using CLBs in a Xilinx FPGA. This approach is very dependent on the technology. For example, we could not easily transfer a design that uses Xilinx CLBs as SRAM to an Actel FPGA.

The last approach, using a custom RAM compiler, is the most area-efficient approach. It depends on having the capability to call a compiler from within the synthesis tool or to instantiate a component that has already been compiled.

12.8.1 Memory Synthesis in Verilog

Most synthesizers implement a Verilog memory array, such as the one shown in the following code, as an array of latches or flip-flops.

reg [31:0] MyMemory [3:0]; // a 4 x 32-bit register

For example, the following code models a small RAM, and the synthesizer maps the memory array to sequential logic:

module RAM_1(A, CEB, WEB, OEB, INN, OUTT);

input [6:0] A; input CEB,WEB,OEB; input [4:0]INN; output [4:0] OUTT;

reg [4:0] OUTT; reg [4:0] int_bus; reg [4:0] memory [127:0]; always @( negedge CEB) begin

if (CEB == 0) begin

if (WEB == 1) int_bus = memory[A];

else if (WEB == 0) begin memory[A] = INN; int_bus = INN; end else int_bus = 5'bxxxxx;

end end

always @(OEB or int_bus) begin case (OEB) 0 : OUTT = int_bus; default : OUTT = 5'bzzzzz; endcase end

endmodule

Memory synthesis using random control logic and transparent latches for each bit is reasonable only for small, fast register files, or for local RAM on an MGA or CBIC. For large RAMs synthesized memory becomes very expensive and instead you should normally use a dedicated RAM compiler.

Typically there will be restrictions on synthesizing RAM with multiple read/writes:

If you write to the same memory in two different processes, be careful to avoid address contention.

You need a multiport RAM if you read or write to multiple locations simultaneously.

If you write and read the same memory location, you have to be very careful. To mimic hardware you need to read before you write so that you read the old memory value. If you attempt to write before reading, the difference between blocking and nonblocking assignments can lead to trouble.

You cannot make a memory access that depends on another memory access in the same clock cycle. For example, you cannot do this:

memory[i + 1] = memory[i]; // needs two clock cycles

or this:

pointer = memory[memory[i]]; // needs two clock cycles For the same reason (but less obviously) we cannot do this:

pc = memory[addr1]; memory[addr2] = pc + 1; // not on the same cycle

12.8.2 Memory Synthesis in VHDL

VHDL allows multidimensional arrays so that we can synthesize a memory as an array of latches by declaring a two-dimensional array as follows:

type memStor is array(3 downto 0) of integer ; -- This is OK.

subtype MemReg is STD_LOGIC_VECTOR(15 downto 0); -- So is this. type memStor is array(3 downto 0) of MemReg;

-- other code...

signal Mem1 : memStor;

As an example, the following code models a standard-cell RAM: library IEEE;

use IEEE.STD_LOGIC_1164. all ; package RAM_package is constant numOut : INTEGER := 8;

constant wordDepth: INTEGER := 8; constant numAddr : INTEGER := 3;

subtype MEMV is STD_LOGIC_VECTOR(numOut-1 downto 0); type MEM is array (wordDepth-1 downto 0) of MEMV;

end RAM_package; library IEEE;

use IEEE.STD_LOGIC_1164. all ; use IEEE.NUMERIC_STD. all ; use work.RAM_package. all ;

entity RAM_1 is

port (signal A : in STD_LOGIC_VECTOR(numAddr-1 downto 0); signal CEB, WEB, OEB : in STD_LOGIC;

signal INN : in MEMV; signal OUTT : out MEMV); end RAM_1;

architecture Synthesis_1 of RAM_1 is

signal i_bus : MEMV; -- RAM internal data latch signal mem : MEM; -- RAM data

begin process begin

wait until CEB = '0';

if WEB = '1' then i_bus <= mem(TO_INTEGER(UNSIGNED(A))); elsif WEB = '0' then

mem(TO_INTEGER(UNSIGNED(A))) <= INN; i_bus <= INN;

else i_bus <= ( others => 'X'); end if ;

end process ;

process (OEB, int_bus) begin -- control output drivers: case (OEB) is

when '0' => OUTT <= i_bus;

when '1' => OUTT <= ( others => 'Z'); when others => OUTT <= ( others => 'X'); end case ;

end process ; end Synthesis_1;

Соседние файлы в папке Для магистратуры