
存储器的设计 寻址存储器(RAM和ROM) ROM和RAM属于通用大规模器件,一般不需要自行设 计,特别是采用PLD器件进行设计时 但是在数字系统中,有时也需要设计一些小型的存储器 件,用于特定的用途:临时存放数据,构成查表运算等。 此类器件的特点为地址与存储内容直接对应,设计时将 输入地址作为给出输出内容的条件; RAM随机存储器 RAM的用途是存储数据,其指标为存储容量和字长; RAM的内部可以分为地址译码和存储单元两部分 外部端口为:wr写读控制cs片选 d数据端口adr地址端口 例16x8位RAM的设计 设计思想 将每个8位数组作为一个字(word);总共存储16个字; 将ram作为由16个字构成的数组,以地址为下标 通过读写控制模式实现对特定地址上字的读出或写入; library ieee Ise ieee std logic 1164. all; use ieee std logic unsigned. all
存储器的设计 寻址存储器(RAM 和 ROM) ROM 和 RAM 属于通用大规模器件,一般不需要自行设 计,特别是采用 PLD 器件进行设计时; 但是在数字系统中,有时也需要设计一些小型的存储器 件,用于特定的用途:临时存放数据,构成查表运算等。 此类器件的特点为地址与存储内容直接对应,设计时将 输入地址作为给出输出内容的条件; RAM 随机存储器 RAM 的用途是存储数据,其指标为存储容量和字长; RAM 的内部可以分为地址译码和存储单元两部分; 外部端口为: wr 写读控制 cs 片选 d 数据端口 adr 地址端口 例 16x8 位 RAM 的设计 设计思想: 将每个 8 位数组作为一个字(word);总共存储 16 个字; 将 ram 作为由 16 个字构成的数组,以地址为下标; 通过读写控制模式实现对特定地址上字的读出或写入; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

entity kram is port( clk, wr, cs: in std logic; d inout std log 0); adr in std logic vector(3 downto O)) end kram architecture beh of kram i subtype word is std logic vector(7 downto 0) type memory is array(0 to 15)of word signal adr in integer range0 to 15 gnal sram memory dr in
entity kram is port ( clk,wr,cs: in std_logic; d: inout std_logic_vector(7 downto 0); adr: in std_logic_vector(3 downto 0)); end kram; architecture beh of kram is subtype word is std_logic_vector(7 downto 0); type memory is array (0 to 15) of word; signal adr_in:integer range 0 to 15; signal sram:memory; begin adr_in<=conv_integer (adr); process(clk) begin if(clk'event and clk='1') then if (cs='1'and wr='1') then sram (adr_in)<=d; end if; if (cs='1'and wr='0' ) then d<=sram (adr_in); end if; end if; end process; end beh; RAM 的数据端口通常为 inout 模式,设置仿真输入时只 能在写入时将信号加到该输入端口上,在其他时候输入应设 置为高阻态; RAM 设计时需要注意器件的大小,一个 16x8 位的 RAM 大约占用 200 个门,而 256x16 的 RAM 则需要 6200 门以上

因此大规模RAM不适合于采用PLD设计,最好采用通用器 ROM只读存储器 ROM的内容是初始设计电路时就写入到内部的,通常采 用电路的固定结构来实现存储;ROM只需设置数据输出端口 和地址输入端口 例1简单ROM的设计(16x8位ROM) 设计思想:采用二进制译码器的设计方式,但将每个输入组 态对应的输出与一组存储数据对应起来; library ieee use ieee std logic 1164. all entity rom Is port(dataout: out std logic vector( 7 downto 0) addr: in std logic vector(3 downto o) ce: in std logic) end rom architecture d of rom is dataout
因此大规模 RAM 不适合于采用 PLD 设计,最好采用通用器 件; ROM 只读存储器 ROM 的内容是初始设计电路时就写入到内部的,通常采 用电路的固定结构来实现存储;ROM 只需设置数据输出端口 和地址输入端口; 例 1 简单 ROM 的设计(16x8 位 ROM) 设计思想:采用二进制译码器的设计方式,但将每个输入组 态对应的输出与一组存储数据对应起来; library ieee; use ieee.std_logic_1164.all; entity rom is port(dataout: out std_logic_vector(7 downto 0); addr: in std_logic_vector(3 downto 0); ce: in std_logic); end rom; architecture d of rom is begin dataout <= "00001111" when addr ="0000" and ce='0' else "11110000" when addr ="0001" and ce='0' else "11001100" when addr ="0010" and ce='0' else "00110011" when addr ="0011" and ce='0' else "10101010" when addr ="0100" and ce='0' else "01010101" when addr ="0101" and ce='0' else "10011001" when addr ="0110" and ce='0' else

" 01100110" when addr=0111" and ce= o' else 00000000"when addr="1000"and ce=o' else 11111111"when addr=1001" and ce=o' else "00010001"when addr=1010"and ce=o' else 10001000"when addr=1011"and ce=0 else 10011001"when addr ="1100"and ce=o' else 01100110" when addr=1101"and ce=o' else 10100110"when addr=1110" and ce=o' else 01100111" when addr="1111"and ce=o else XXXXXXXX 对于较大的ROM,可以采用结构设计的方法,直接调用 参数化模块进行设计 例ROM的LPM设计(256x8位ROM library ieee, use ieee std logic 1164. all library lpm use lpm Ipm components.all; port(address in std logic vector(7 downto 0); clock in std logic. g: out std logic vector(7 downto O)); d ron architecture str of romlpm is signal sub wireD: std logic vector(7 downto 0) q8 m w
"01100110" when addr ="0111" and ce='0' else "00000000" when addr ="1000" and ce='0' else "11111111" when addr ="1001" and ce='0' else "00010001" when addr ="1010" and ce='0' else "10001000" when addr ="1011" and ce='0' else "10011001" when addr ="1100" and ce='0' else "01100110" when addr ="1101" and ce='0' else "10100110" when addr ="1110" and ce='0' else "01100111" when addr ="1111" and ce='0' else "XXXXXXXX"; end d; 对于较大的 ROM,可以采用结构设计的方法,直接调用 参数化模块进行设计; 例 ROM 的 LPM 设计 (256x8 位 ROM) library ieee; use ieee.std_logic_1164.all; library lpm; use lpm.lpm_components.all; entity romlpm is port(address: in std_logic_vector(7 downto 0); inclock: in std_logic; q: out std_logic_vector(7 downto 0)); end romlpm; architecture str of romlpm is signal sub_wire0:std_logic_vector(7 downto 0); begin q8, lpm_widthad =>8

Ipm address control=>"registered Ipm outdata=>"unregistered pm file→>"krom2mif") port map( address=>address inclock->inclock q=>sub wire) end str: ROM的初始化 在ROM的设计中,必须要预先设置好数据存储文件,这 是一种以mf为后缀的文本文件,在任何文本编辑器中,按如 下文件格式写入: DEPTH=16;字线数量 WIDT 位线数量 ADDRESS RADIX=HEX;地址与数据的表达类型 DATA RADIX=HEX;可以选择: HEX OCT DEC BIN CONTENT 存储内容地址:数据 BEGIN [0.F] 4567; FE5 END 文件写完后,保存为mif即可。 例:4位查表式乘法器设计 功能:将两个4位二进制数A和B相乘,输出乘积结果 C(8位二进制数) 设计方案:采用256x8位ROM实现,8位地址输入(高 4位为A,低4位为B),256个存储字;8位数据输出 数据存储文件(krom2.mif):填写相应的乘法表即可 depth=256; width=8
lpm_address_control=>"registered", lpm_outdata => "unregistered", lpm_file=> "krom2.mif") port map( address=>address, inclock=>inclock, q =>sub_wire0); end str; ROM 的初始化 在 ROM 的设计中,必须要预先设置好数据存储文件,这 是一种以.mif 为后缀的文本文件,在任何文本编辑器中,按如 下文件格式写入: DEPTH = 16; 字线数量 WIDTH = 4; 位线数量 ADDRESS_RADIX = HEX; 地址与数据的表达类型 DATA_RADIX = HEX; 可以选择:HEX OCT DEC BIN CONTENT 存储内容 地址 :数据; BEGIN [0..F] : 3; 2 : 4 5 6 7; 8 : F E 5; END ; 文件写完后,保存为.mif 即可。 例:4 位查表式乘法器设计 功能:将两个 4 位二进制数 A 和 B 相乘,输出乘积结果 C(8 位二进制数); 设计方案:采用 256x8 位 ROM 实现,8 位地址输入(高 4 位为 A,低 4 位为 B),256 个存储字;8 位数据输出; 数据存储文件(krom2.mif): 填写相应的乘法表即可 depth = 256; width = 8;

address radix= hex data radix hex content [00.0f]:00; 10:000102030405060708090a0b0c0doe0f, 20:00020406080a0c0e1012141618 la lc le; 30:000306090c0f121518ble2124272a2d 40:0004080c101418lc2024282c3034383c 50:00050aof1419ld23282d32373c41464b 60:00060c1218le242a30363c42484e545a 70:00070e15lc232a31383f464d545b6269 80:00081018202830384048505860687078; 90:009121b242d363f48515a636c757e87; a0:000a14le28323c46505a646e78828c96; b0:000b16212c37424d58636e79848f9aa5 c0:000c1824303c4854606c7884909ca8b4 d0:000dla27344l4e5b6875828f9ca9b6c3; e0:000elc2a38465462707e8c9aa8b6c4d2 f0: 00 Of le 2d 3c 4b 5a 66788796 a5 b4 c3 d2 el end 该乘法器ROM设计完毕后,将其设置为符号文件,将来 就可以在VHDL程序中用 component语句调用了。 在 maxplus2的仿真器窗口内,也可以直接生成ROM的 初始化文件,其步骤如下 选择 Initialize/ nitialize Memory 按ROM地址输入数据 存盘即可生成指定的mif文件(文件名已经在结构体内 指明)
address_radix = hex; data_radix = hex; content begin [00..0f] : 00 ; 10 : 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f; 20 : 00 02 04 06 08 0a 0c 0e 10 12 14 16 18 1a 1c 1e; 30 : 00 03 06 09 0c 0f 12 15 18 1b 1e 21 24 27 2a 2d; 40 : 00 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c; 50 : 00 05 0a 0f 14 19 1d 23 28 2d 32 37 3c 41 46 4b; 60 : 00 06 0c 12 18 1e 24 2a 30 36 3c 42 48 4e 54 5a; 70 : 00 07 0e 15 1c 23 2a 31 38 3f 46 4d 54 5b 62 69; 80 : 00 08 10 18 20 28 30 38 40 48 50 58 60 68 70 78; 90 : 00 09 12 1b 24 2d 36 3f 48 51 5a 63 6c 75 7e 87; a0 : 00 0a 14 1e 28 32 3c 46 50 5a 64 6e 78 82 8c 96; b0 : 00 0b 16 21 2c 37 42 4d 58 63 6e 79 84 8f 9a a5; c0 : 00 0c 18 24 30 3c 48 54 60 6c 78 84 90 9c a8 b4; d0 : 00 0d 1a 27 34 41 4e 5b 68 75 82 8f 9c a9 b6 c3; e0 : 00 0e 1c 2a 38 46 54 62 70 7e 8c 9a a8 b6 c4 d2; f0 : 00 0f 1e 2d 3c 4b 5a 66 78 87 96 a5 b4 c3 d2 e1; end; 该乘法器 ROM 设计完毕后,将其设置为符号文件,将来 就可以在 VHDL 程序中用 component 语句调用了。 在 maxplus2 的仿真器窗口内,也可以直接生成 ROM 的 初始化文件,其步骤如下: 选择 Initialize/Initialize Memory…; 按 ROM 地址输入数据; 存盘即可生成指定的 mif 文件(文件名已经在结构体内 指明);

顺序存储器(堆栈和FIFO) 顺序存储器的特点是不设置地址,所有数据的写入和读 出都按顺序进行;数据写入或读出时通常会进行移位操作; 在设计时必须考虑各存储单元的存储状态: 堆栈(后进先出存储器) 要求:存入数据按顺序排放,存储器全满时给出信号并拒绝 继续存入;读出时按后进先出原则;存储数据一旦读出就从 存储器中消失; 设计思想: 将每个存储单元设置为字(word):存储器整体作为由字 构成的数组;为每个字设置一个标记(fag),用以表达该存 储单元是否已经存放了数据;每写入或读出一个数据时,字 的数组内容进行相应的移动,标记也做相应的变化 程序示例: use ieee std logic 1164. all use ieee std logic arith. all port(datain: in std logic vector(7 downto O); push, pop, reset, clk in std logic stackfull: out std logic, dataout: buffer std logic vector(7 downto O)) end stack
顺序存储器(堆栈和 FIFO) 顺序存储器的特点是不设置地址,所有数据的写入和读 出都按顺序进行;数据写入或读出时通常会进行移位操作; 在设计时必须考虑各存储单元的存储状态; 堆栈(后进先出存储器) 要求:存入数据按顺序排放,存储器全满时给出信号并拒绝 继续存入;读出时按后进先出原则;存储数据一旦读出就从 存储器中消失; 设计思想: 将每个存储单元设置为字(word);存储器整体作为由字 构成的数组;为每个字设置一个标记(flag),用以表达该存 储单元是否已经存放了数据;每写入或读出一个数据时,字 的数组内容进行相应的移动,标记也做相应的变化; 程序示例: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_signed.all; entity stack is port(datain: in std_logic_vector(7 downto 0); push,pop,reset,clk:in std_logic; stackfull:out std_logic; dataout: buffer std_logic_vector(7 downto 0)); end stack;

architecture b of stack is type arraylogic is array (15 downto 0) of std logic vector(7 signal stackflag: std logic vector(15 downto O) stackfull0); dataout0) for i in 0 to 15 loop data(1) if stackflag(00 then data(15)=datain stackflagnull end case
architecture b of stack is type arraylogic is array(15 downto 0) of std_logic_vector(7 downto 0); signal data :arraylogic; signal stackflag:std_logic_vector(15 downto 0); begin stackfull'0'); dataout'0'); for i in 0 to 15 loop data(i) if stackflag(0)=’0’ then data(15) dataoutnull; end case;

end if end process 以上程序是基于移位寄存器的设计思想;若基于存储器 的设计思想,则可以设置一个指针( point),表示出当前写入 或读出单元的地址,使这种地址进行顺序变化,就可以实现 数据的顺序读出或写入 程序示例 library说明和entt设计与上面程序完全相同 chitecture b of stack type arraylogic is array(15 downto 0) of std logic vector(7 downto 0) signal data arraylogic process(clk, reset, pop, push) variable p natural range 0 to 15 variable selfunction: std logic vector( I downto 0) variable s std logic beg selfunction: =push& pop; if reset='l' then for i in 0 to 15 loop data()
end if; end process; end b; 以上程序是基于移位寄存器的设计思想;若基于存储器 的设计思想,则可以设置一个指针(point),表示出当前写入 或读出单元的地址,使这种地址进行顺序变化,就可以实现 数据的顺序读出或写入; 程序示例 library 说明和 entity 设计与上面程序完全相同; architecture b of stack is type arraylogic is array(15 downto 0) of std_logic_vector(7 downto 0); signal data :arraylogic; begin process(clk,reset,pop,push) variable p:natural range 0 to 15; variable selfunction: std_logic_vector(1 downto 0); variable s:std_logic; begin stackfull'0');s:='0'; for i in 0 to 15 loop data(i)<="00000000"; end loop; elsif clk'event and clk='1' then if p<15 and selfunction="10" then data(p)<=datain; p:=p+1; end if; if p=15 and selfunction="10" and s='0' then

data(p)=datain; S:=l if p>0 and selfunction="01"and s=0 then p:=p-1; dataout
data(p)0 and selfunction="01" and s='0' then p:=p-1; dataout<=data(p); end if; if p=15 and selfunction="01" and s='1' then dataout<=data(p); s:='0'; end if; end if; end process; end b; FIFO(先进先出存储器) 要求:存入数据按顺序排放,存储器全满时给出信号并拒绝 继续存入,全空时也给出信号并拒绝读出;读出时按先进先 出原则;存储数据一旦读出就从存储器中消失; 设计思想: 结合堆栈指针的设计思想,采用环行寄存器方式进行设 计;分别设置写入指针 wp 和读出指针 rp,标记下一个写入地 址和读出地址;地址随写入或读出过程顺序变动;设置全空 标记和全满标记以避免读出或写入的错误; 设计时需要注意处理好从地址最高位到地址最地位的变 化; 程序示例 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_signed.all;