第6章 VHDL程序设计
第六章:VHDL程序设计
§6.1 VHDL描述风格
·描述风格:VHDL的构造体用于描述整个设计实体的逻辑功能。对于相同的电路功能行为,可以用不同的描述方式来表达;对于相同的逻辑行为,可以用不同的语句来描述。
·类型:行为描述;
寄存器传递(数据流)描述;
结构描述。
1.行为描述方式
·含义:是对系统数学模型的描述。
·特点:①只表示输入与输出间转换的行为,而不包含任何结构信息;
②主要使用函数、过程和进程语句,以算法形式描述数据的变换和传送;
③比寄存器传递和结构描述具有更高的抽象性;
④行为描述是VHDL编程的核心,可以说,没有行为描述就没有VHDL。
⑤通常不能直接进行逻辑综合,需要转化成RTL描述或结构描述。
·用途:主要用于系统数学模型的仿真或系统工作原理的仿真。
[例6-1]用行为描述方式描述“二选一”电路功能。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY mux2 IS i1
PROT( i0, i1, sel : IN STD_LOGIC;
q: OUT STD_LOGIC ); sel
END mux2;
ARCHITECTURE behav OF mux2 IS
BEGIN
CASE sel IS
WHEN 0 =>q<=i0 AFTER 10ns;
WHEN 1 =>q<=i1 AFTER 10ns;
WHEN OTHERS=>q<=‘X‘ AFTER 10ns;
END CASE
END behav;
2.寄存器传递描述(RTL)方式
·含义:是一种明确规定寄存器描述的方法。
·分类:①采用寄存器之间的功能描述(类似行为描述);
②采用寄存器硬件直接描述(一一对应)。
·特点:①RTL功能描述编程效率高、难度低,但可用的VHDL语句受限;
②RTL硬件描述编程难度大、要求高,但可用的VHDL语句多。[例6-2] 用RTL硬件方式描述“二选一”电路功能。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY mux2 IS
PROT( i0, i1, sel : IN STD_LOGIC;
q: OUT STD_LOGIC );
END mux2;
ARCHITECTURE rtl OF mux2 IS
SIGNAL temp1, temp2, temp3, : STD_LOGIC;
BEGIN
Temp1<=i0 AND sel;
Temp2<=i1 AND (NOT sel);
Temp3<=temp1 OR temp2;
q<=temp3;
END rtl;
3.结构描述方式
·含义:在分层设计中,通过高层次的设计模块调用低层次的设计模块来构成一个复杂的逻辑电路的描述方法。
·特点:①结构清晰,与硬件层层对应,如:系统→板→元件;
②设计效率高,可方便地将已有设计成果用到新的设计中。
[例6-3]用结构描述方式描述“二选一”电路功能。
U3
d0
d1
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY mux2 IS
PROT(d0, d1, sel : IN BIT;
q: OUT BIT );
END mux2;
ARCHITECTURE struct OF mux2 IS
COMPONENT and2
PROT(a, b : IN BIT;
c: OUT BIT );
END COMPONET;
COMPONENT or2
PROT(a, b : IN BIT;
c: OUT BIT );
END COMPONET;
COMPONENT inv
PROT(a : IN BIT;
c: OUT BIT );
END COMPONET;
SIGNAL aa, bb, nsel: BIT;
BEGIN
U1: inv PORT MAP(sel, nsel);
U2: and2 PORT MAP(d1, nsel, bb);
U3: and2 PORT MAP(d0, sel, aa);
U4: or2 PORT MAP(aa, bb, q);
END struct;
说明:①COMPONENT语句用来说明在该电路中所使用的已生成的模块and2,…;
②PORT MAP( ) 语句将已生成模块的端口与所设计的各模块U1,U2…的端口连接起来。
§6.2 组合逻辑电路设计
1.基本门电路
[例6-4] 用VHDL程序描述二输入“异或”门电路。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY xor2 IS
PORT (a, b: IN STD_LOGIC;
y: OUT STD_LOGIC);
END xor2;
ARCHITECTURE xor2_1 OF xor2 IS
BEGIN
y<=a XOR b;
END xor2_1;
[例6-5] 用VHDL 程序描述二输入“异或”门电路。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY xor2 IS
PORT (a, b: IN STD_LOGIC;
y: OUT STD_LOGIC);
END xor2;
ARCHITECTURE xor2_2 OF xor2 IS
BEGIN
PROCESS(a, b)
V ARIABLE comb:STD_LOGIC VECTOR( 1 DOWNTO 0 );
BEGIN
Comb:= a & b;
CASE comb is
WHEN ―00‖=> y <=‘0‘;
WHEN ―01‖=> y <=‘1‘;
WHEN ―10‖=> y <=‘1‘;
WHEN ―11‖=> y <=‘0‘;
WHEN OTHERS=> y <=‘X‘;
END CASE;
END PROCESS;
END xor2_2;
2.加法器
(1) 半加器
真值表 电路符号
二进制输入 和
进位
b a s co
0 0 0 0
0 1 1 0 1 0 1 0
1 1 0 1
逻辑表达式: S = (a + b)·/(a·b)
C0 = /(a·b)
[例6-6] 用VHDL 程序描述半加器电路功能。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY half_adder IS
PORT (a, b: IN STD_LOGIC;
s, co: OUT STD_LOGIC);
END half_adder;
ARCHITECTURE half1 OF half_adder IS
SIGNAL c, d: STD_LOGIC;
BEGIN
c<=a OR b;
d<=a NAND b;
s<=c AND d;
co<=NOT d;
END half1;
(2)全加器
[例6-7] 用VHDL程序描述全加器电路功能。
a
b
分析:·用两个半加器构成一个全加器;
·原理电路图示意;:
·采用元件例化语句COMPONET---PORT MAP( )。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY full_adder IS
PORT (a, b, ci: IN STD_LOGIC;
s, co: OUT STD_LOGIC);
END full_adder;
ARCHITECTURE full1 OF full_adder IS
COMPONENT half_adder
PORT (a, b: IN STD_LOGIC;
s, co: OUT STD_LOGIC);
END COMPONENT;
SIGNAL u0_s, u0_co, u1_s, u1_co: STD_LOGIC;
BEGIN
U0:half_adder PORT MAP(a, b, u0_s,u0_co);
U1:half_adder PORT MAP(ci, u0_s, u1_s, u1_co);
s<=u1_s;
co<=u0_co OR u1_co;
END fall1;
3.其它
编码器(优先级)/译码器(3-8)/选择器(四选一)/缓冲器(单/双)等(自学)
§6.3 时序电路设计
1.时钟信号
(1) 含义:周期性系列脉冲
(2) 作用:是描述时序电路的VHDL程序执行的条件。
(3) 描述方式:以进程的形式描述时序电路。
①时钟信号是进程的敏感信号
如:PROCESS (clk_signal)
BEGIN
IF (clock_edge_condition) THEN
Signal_out <= signal_in
…
END IF;
END PROCESS;
②时钟信号是进程中的激活信号
如:PROCESS
BEGIN
WAIT ON (clock_signal) UNTIL (clock_edge_condition)
Signal_out<=signal_in
…
END PROCESS;
(4) 边沿触发
①上升沿
·图形描述:
·语句描述:
IF clk=‘1‘AND clk‘LAST_V ALUE=‘0‘AND clk‘EVENT;
②下升沿
·图形描述:
·语句描述:
IF clk=‘0‘AND clk‘LAST_V ALUE=‘1‘AND clk‘EVENT;
2.复位信号
(1) 类型:·同步复位:当复位信号有效且给定时钟边沿到来时,触发器才被
复位。
·非同步复位(异步复位):一旦复位信号有效,触发器就被复位。
(2) 描述方式:
①同步复位:一定在以时钟为敏感信号的进程中定义,且用IF语句来描述必要的复位条件。
如:PROCESS (clock_signal)
BEGIN
IF (clock_edge_condition) THEN
IF (reset_condition) THEN
Signal_out<= reset_value;
ELSE
Signal_out<= signal_in;
…
END IF;
END IF;
END PROCESS;
②异步复位:在进程的敏感信号中,时钟和复位信号同时存在,用IF语句描述复位条件,用ELSE语句描述时钟事件。
如:PROCESS (reset_signal,clock_signal)
BEGIN
IF (reset_condition) THEN
Signal_out<= reset_value;
ELSIF (clock_event AND clock_edge_condition) THEN
Signal_out<= signal_in;
…
END IF;
END PROCESS;
说明:若没有ELSIF语句,当复位信号变化但复位条件不满足时…。
3.触发器
[例6-8] 用VHDL程序描述D触发器功能
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY dff1 IS
PROT(d, clk: IN STD_LOGIC;
q: OUT STD_LOGIC);
END dff1;
ARCHITECTURE rtl Of dff1 IS
BEGIN
PROCESS(clk)
BEGIN
IF (clk=‘1‘) AND (clk‘EVENT) THEN
q<=d;
END IF;
END PROCESS
END rtl;
讨论:①本例是一个上升沿触发的D触发器程序;
②若改为下降沿触发:
clk‘EVENT AND clk=‘1‘→ clk=‘0‘
③若改用WAIT语句、上升沿触发:
IF →WAIT UNTIL clk‘EVENT AND clk=‘1‘
④若改用WAIT语句、下降沿触发:
IF →WAIT UNTIL clk‘EVENT AND clk=‘0‘[例6-9] 用VHDL程序描述异步置位/复位锁存器功能LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY dffcs IS
PROT(d, clk, clr, set: IN STD_LOGIC;
q: OUT STD_LOGIC);
END dffcs;
ARCHITECTURE rtl Of dffcs IS
BEGIN
PROCESS(clk, clr, set)
BEGIN
IF (clr=‘0‘) THEN
Q <= ‘0‘;
ELSIF (SET=‘0‘) THEN
Q <= ‘1‘;
ELSIF (clk‘EVENT AND clk=‘1‘) THEN
Q <= d;
END IF;
END PROCESS
END rtl;
[例6-10] 用VHDL程序描述J-K触发器功能
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY jkff IS
PROT(j, k, clk, clr, set: IN STD_LOGIC;
Q, qb: OUT STD_LOGIC);
END jkff;
ARCHITECTURE rtl Of jkff IS
SIGNAL q_s, qb_s: STD_LOGIC;
BEGIN
PROCESS(clk, clr, set, j, k)
BEGIN
IF (clr=‘0‘) AND (set=‘1‘) THEN
Q_s <= ‘0‘;
Qb_s <= ‘1‘;
ELSIF (clr=‘1‘) AND (set=‘0‘) THEN
Q_s <= ‘1‘;
Qb_s <= ‘0‘;
ELSIF (clk‘EVENT AND clk=‘1‘) THEN
IF (j=‘0‘) AND (k=‘1‘) THEN
Q_s <= ‘0‘;
Qb_s <= ‘1‘;
ELSIF (j=‘1‘) AND (k=‘0‘) THEN
Q_s <= ‘1‘;
Qb_s <= ‘0‘;
ELSIF (j=‘1‘) AND (k=‘1‘) THEN
Q_s <= NOT q_s;
Qb_s <= NOT qb_s;
ELSE
Q_s <= q_s;
Qb_s <= qb_s;
END IF;
Q <= q_s;
Qb <= qb_s;
END PROCESS
END rtl;
4.寄存器
[例6-11] 用VHDL语言设计一硬件电路,实现8位并入/并出移位寄存器循环左移3位。
分析:①电路符号
其中:din(0)~din(7): 8个数据输入端;
dout(0)~dout(7): 8个数据输出端;
s(0)~s(2): 移位位数控制输入端;
enb: 移位/数据输出控制端;
当enb=‘1’时,移位寄存器椐s(0)~s(2)输入的数据确
定循环左移的位数;
当enb=‘0’时,输出dout = din
clk: 移位时钟输入端。
②工作原理
sc = 3位(左移)din(7) din(0)
LSB
LSB Dout(7) dout(0)
③首先设计一个8位循环左移寄存器过程,以供其他调用;
④调用上述过程,设计一8位并入/并出移位寄存并循环左移3位。
※※用VHDL语言设计一循环左移“shift过程”
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
PACKAGE CPAC IS
PROCEDURE shift(din, s: IN STD_LOGIC_VECTOR;
SIGNAL dout: OUT STD_LOGIC_VECTOR );
END CPAC;
PACKGE BODY CPAC IS
PROCEDURE shift(din, s: IN STD_LOGIC_VECTOR;-过程名(参数)
SIGNAL dout: OUT STD_LOGIC_VECTOR ) IS
V ARIABLE sc:INTEGER; --定义变量
BEGIN
SC:=CONV_INTEGER(S); ---位矢量→整数
FOR I IN din‘RANGE LOOP
IF (sc+i <= din‘LEFT) T HEN ---3+I <=7
Dout(sc+I) <= din(i); --左边5位处理
ELSE
dout(sc + I - din‘LEFT-1) <=din(i); --右边3位处理
END IF;
END LOOP;
END shift;
END CPAC;
※※用VHDL语言通过调用上面程序包中的“shift过程”,实现3位循环左移。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.CPAC.ALL;
ENTITY bsr IS
Port( din: IN STD_LOGIC_VECTOR(7 DOWN 0);
S: IN STD_LOGIC_VECTOR(2 DOWN 0);
Dout: OUT STD_LOGIC_VECTOR(7 DOWN 0);
Clk, enb: IN STD_LOGIC);
END bsr;
ARCHITECTURE rtl OF bsr IS
BEGIN
PROCESS (clk)
BEGIN
IF (clk‘EVENT AND clk=‘1‘) THEN
IF (enb=‘0‘) THEN
Dout <= din;
ELSE
Shift (din, s, dout); ---调用程序包CPAC中的“shift过程”
END IF;
END IF;
END PROCESS;
END rtl;
5.计数器
·分类:
同步:在计数时钟控制下,构成计数器的各触发器状态同步发生变化;
异步:低位计数输出作为高一位计数器的时钟信号,一级一级串行连接。[例6-12] 用VHDL语言设计一六十进制计数器。
分析:①用一个六进制和一个十进制计数器连接起来→60进制计数器
②电路引脚图
clk
bcd1(0)
(1)
(2)
(3)
bcd10(0)
(1)
(2)
con
③引脚说明:
clk: 时钟输入
bcd1w: 个位置数控制端
bcd10w: 十位置数控制端
cin: 个位向十位进位输入端
con: 十位进位输出端
datain(0)~(3): 个位/十位预制数据输入端
bcd1(0)~(3): 个位数据输出端
bcd10(0)~(3): 十位数据输出端(最大为5)
④工作原理:
·bcd1w和bcd10w与datain(0)~(3)配合完成个位和十位预置数。因公用一组输入数据线,所以分别用两个进程串行完成;
·用三个进程分别处理个位、十位计数和进位处理。
VHDL语言源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY bcd60count IS
Port(clk, bcd1w, bcd10w, cin: IN STD_LOGIC;
co: OUT STD_LOGIC;
Datain: IN STD_LOGIC_VECTOR(3 DOWN 0);
Bcd1: OUT STD_LOGIC_VECTOR(3 DOWN 0);
Bcd10: OUT STD_LOGIC_VECTOR(2 DOWN 0));
END bcd60count;
ARCHITECTURE rtl OF bcd60count IS
SIGNAL bcd1n: STD_LOGIC_VECTOR(3 DOWN 0); SIGNAL bcd10n: STD_LOGIC_VECTOR(2 DOWN 0); BEGIN
Bcd1<= bcd1n;
Bcd10<= bcd10n;
PROCESS (clk, bcd1w) ---个位置数/计数BEGIN
IF (bcd1w=‘1‘) THEN
Bcd1n<= datain;
ELSIF (clk‘EVENT AND clk=‘1‘) THEN
IF (cin=‘1‘) THEN----加1计数IF (bcd1n=‘9‘) THEN
Bcd1n<=‖0000‖;
ELSE
Bcd1n<=bcd1n+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (clk, bcd10w) ---十位置数/计数BEGIN
IF (bcd10w =‘1‘) THEN
Bcd10n<= datain(2 DOWNTO 0);
ELSIF (clk‘EVENT AND clk=‘1‘) THEN
IF (cin=‘1‘ AND bcd1n=‘9‘) THEN
IF (bcd10n=‘5‘) THEN
Bcd10n<=‖000‖;
ELSE
Bcd10n<=bcd10n+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS(bcd10n, bcd1n, cin)
BEGIN
IF (cin=‘1‘ AND bcd1n=‘9‘ AND bcd10n=‘5‘) THEN
c o<=‘1‘;
ELSE
c o<=‘0‘;
END IF;
END PROCESS;
END rtl;
6.存储器
主要内容:ROM、RAM、FIFO等
1)基本概念
(1)存储器的描述
·存储器中存放的数据与数组中的元素相对应
·用整数表示元素的数组描述存储器的结构:
TYPE memory IS ARRAY (INTEGER RANEG<>) OF INTEGER;
·用位矢量表示元素的数组描述存储器的结构:
SUBTYPE word IS STD_LOGIC_VECTOR(k-1 DOWNTO 0);
TYPE memory IS ARRAY (0 TO 2**w -1) OF WORD;
其中:k表示存储单元的二进制位数,
w表示数组的元素个数。
(2)存储器的初始化
·实现方法:通过读取外部文件获得原始数据,然后赋给数组变量。
·变量说明:
V ARIABLE startup: BOOLEAN:=TRUE;
V ARIABLE l: LINE;
V ARIABLE j: INTEGER;
V ARIABLE rom: memory;
FILE romin:TEXT IS IN ―rom24s10.in‖
·初始化程序:
IF startup THEN
FOR j IN rom‘RANGE LOOP
READLINE(romin,l);
READ(l,rom(j));
END LOOP;
END IF;
2)只读存储器(ROM)
[例6-13] 试用VHDL设计一只读存储器(ROM)。
要求:①存储器容量:4K*8bit
②当rd、cs信号均为高电平时,输出数据;否则输出呈高阻状态。
分析:地址线:12条adr(0) — adr(11)
·数据线:8条dout(0) — dout(7)
·控制线:2条rd、cs
·存储器引脚图
·
··
·
·
源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY roms IS
PORT ( rd, cs: IN STD_LOGIC;
adr: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
dout: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END roms;
ARCHITECTURE behav OF roms IS
SUBTYPE word IS STD_LOGIC_VECTOR(7 DOWNTO 0);
TYPE memory ARRAY (0 TO 4095) OF word ;
SIGNAL adr_in: INTEGER RANGE 0 TO 4095;
V ARIABLE startup: BOOLEAN:=TRUE;
V ARIABLE l: LINE;
V ARIABLE j: INTEGER;
V ARIABLE rom: memory;
FILE romin:TEXT IS IN ―roms.in‖;
BEGIN
PROCESS(rd, cs, adr)
IF startup THEN
FOR j IN rom‘RANGE LOOP
READLINE(romin,l);
READ(l,rom(j));
END LOOP;
startup:= FALSE;
END IF;
adr_in <=CONV_INTEGER(adr);
IF ( rd=‘1‘ AND cs=‘1‘ ) THEN
dout <= rom(adr_in);
ELSE
Dout <= ―zzzzzzzz‖;
END IF;
END PROCESS
END behav;
3)随机读写存储器(RAM)
[例6-14 ] 试用VHDL设计一随机读写存储器(RAM)。
要求:①存储器容量:8*8bit;
②当cs = 1,rd= 0, wr = 1时,由adr 指定的单元内容从dout数据线上输出;
③当cs = 1,rd= 1, wr上升沿到来时,din数据线的数据写入由adr 指定的单元;
分析:①信号线
·地址线:3条adr(0) — adr(2)
·数据输入线:8条din(0) — din(7)
·数据输出线:8条dout(0) — dout(7)
·控制线:3条rd,wr,cs
②存储器引脚图
··
··
··
③存储器操作:
读/写两种操作对时间都有比较严格的要求。写数据时,数据线上数据建立时间必须大于800ps,数据保持时间必须大于300ps。
源程序:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY sram8 IS
GENERIC(k: INTEGER:= 8;
w: INTEGER:= 3 );
PORT ( wr, rd, cs: IN STD_LOGIC;
adr: IN STD_LOGIC_VECTOR(w-1 DOWNTO 0);
din: IN STD_LOGIC_VECTOR(k-1 DOWNTO 0);
dout: OUT STD_LOGIC_VECTOR(k-1 DOWNTO 0));
END sram8;
ARCHITECTURE behav OF sram8 IS
SUBTYPE word IS STD_LOGIC_VECTOR(k-1 DOWNTO 0);
TYPE memory IS ARRAY (0 TO 2**w -1) OF word ;
SIGNAL adr_in: INTEGER RANGE 0 TO 2**w -1;
SIGNAL sram: memory;
SIGNAL din_change, wr_rise,: TIME:= 0ps;
BEGIN
Adr_in <= CONV_INTEGER(adr);
PROCESS(wr) -- 写进程
BEGIN
IF (wr‘EVENT AND wr=‘1‘) THEN
IF (cs=‘1‘ AND wr=‘1‘) THEN
Sram (adr_in)<=din AFTER 2 ns;
END IF;
END IF;
wr_rise<=NOW; -- 数据建立时间检查
ASSERT (NOW-din_change>=800 ps) –若<800ps报警
REPORT‖SETUP ERROR din(sram)‖–表明数据线上的
SEVERITY WARNING; -- 数据未达到稳定END PROCESS; --(ASSERT语句条件为“假”,报告错误)
PROCESS (rd, cs) -- 读进程
BEGIN
IF (rd=‘0‘ AND cs=‘1‘) THEN
dout<=sram(adr_in) AFTER 3 ns;
ELSE
dout<=‖zzzzzzzz‖ AFTER 4 ns;
END IF;
END PROCESS;
PROCESS (din)
BEGIN
din_change<=NOW;
ASSERT (NOW-wr_rise>=300ps) -- 数据保持时间检查
REPORT ―HOLD ERROR din(sram)‖–若<300ps报警
SEVERITY WARNING; -- 表明数据有效时间END PROCESS; -- 太短,不能保证可
END behav; -- 靠写入
4)先进先出缓冲器(FIFO)
[例6-15 ] 试用VHDL设计一先进先出缓冲器(FIFO)。
要求:①存储器容量:8 * 4bit;
②当WR=0且FULL=0时,DIN的数据压入FIFO;
③当RD=0且EMPTY=0时,新的数据从DOUT输出。
分析:①信号线
·数据输入线:4条DIN(0) — DIN(3)
·数据输出线:4条DOUT(0) — DOUT(3)
·时钟线:1条CLK
·控制线:2条WR, RD
·状态线:2条FULL, EMPTY
②存储器示意图
06H
05H
04H
03H
02H
01H
③ WP: 写指示器,指示待写入单元地址;
RP:读指示器,指示已读出单元地址,读新值RP=RP+1
④ FIFO复位后,WP=0,RP=7,FIFO处于空状态;
⑤满信号产生条件:在RP=WP时,再写一个数据进入满状态;
空信号产生条件:在RP=WP-2时,再读一个数据进入空状态;源程序:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY fifo IS
GENERIC(k: INTEGER:=4;
w: INTEGER:= 8 );
PORT ( clk, reset, wr, rd: IN STD_LOGIC;
din: IN STD_LOGIC_VECTOR(k-1 DOWNTO 0);
dout: OUT STD_LOGIC_VECTOR(k-1 DOWNTO 0)
full, empty: OUT STD_LOGIC );
END fifo;
ARCHITECTURE behav OF fifo IS
SUBTYPE word IS STD_LOGIC_VECTOR(k-1 DOWNTO 0);
TYPE memory IS ARRAY (0 TO w -1) OF word ;
SIGNAL ram: memory;
SIGNAL wp, rp: INTEGER RANGE 0 TO w-1
SIGNAL in_full, in_empty: STD_LOGIC; ----中间变量
BEGIN
full<= in_full;
empty<=in_empty;
dout<=ram(rp);
PROCESS (clk) -- 数据写入缓冲区BEGIN
IF (clk‘EVENT AND clk=‘1‘) THEN
IF (wr=‘0‘ AND in_full=‘0‘) THEN
ram (wp)<=din ;
END IF;
END IF;
END PROCESS;
PROCESS (clk, reset) ----写数据指针修改(wp)BEGIN
IF (reset=‘1‘ ) THEN
wp<=0;
‘EVENT AND clk=‘1‘) THEN
‘0‘ AND in_full=‘0‘) THEN
wp<=0; ----缓冲区首尾相连
ELSE
wp<=wp+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (clk, reset) ----读数据指针修改(rp)BEGIN
IF (reset=‘1‘ ) THEN
rp<=w-1;
ELSEIF (clk‘EVENT AND clk=‘1‘) THEN
IF (rp=‘0‘ AND in_empty=‘0‘) THEN
IF (rp=w-1) THEN
rp<=0; ----缓冲区首尾相连
ELSE
rp<=rp+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (clk, reset) ---空标志的产生(empty=‘1’)BEGIN
IF (reset=‘1‘ ) THEN
in_empty<= ?1‘;
ELSEIF (clk‘EVENT AND clk=‘1‘) THEN
IF ((rp=wp-2 ----中间部位
OR (rp=w-1 AND wp=1) ---- 上部
OR (rp=w-2 AND wp=0)) ---- 下部
AND (rd=‘0‘ AND wr=‘1‘)) THEN
in_empty<= ?1‘; --“空”
ELSEIF (in_empty=‘1‘ AND wr=‘0‘) THEN
in_empty<= ?0‘; -- “不空”
END IF;
END IF;
END PROCESS;
PROCESS (clk, reset) ---满标志的产生(full=‘1‘)BEGIN
IF (reset=‘1‘ ) THEN
in_full<= ?0‘;
ELSEIF (clk‘EVENT AND clk=‘1‘) THEN
IF (rp=wp AND wr=‘0‘ and rd=‘1‘) THEN
in full<= ?1‘; -- “满”
ELSEIF (in_full=‘1‘ AND rd=‘0‘) THEN
in_full<= ?0‘; -- “不满”
END IF;
END IF;
END PROCESS
END behav;
/end/