今天给大侠带来的是一周掌握 FPGA VHDL Day 3,今天开启第三天,下面咱们废话就不多说了,一起来看看吧。每日十分钟,坚持下去,量变成质变。
VHDL语言
三、VHDL语句
3.1 并行语句
在结构体中的执行是同时进行,执行顺序与书写顺序无关。
并行信号赋值语句
a. 简单赋值语句
目标信号名 <= 表达式(目标信号的数据类型与右边表达式一致)
ARCHITECTURE Behavior OF FreDevider IS
SIGNAL Clk:Std_Logic;
BEGIN
PROCESS(Clock)
BEGIN
IF rising_edge(Clock) THEN
Clk<=NOT Clk;
END IF;
END PROCESS;
Clkout<=Clk;
b. 选择信号赋值语句
WITH 选择表达式 SELECT
赋值目标信号 <= 表达式1 WHEN 选择值1,
表达式2 WHEN 选择值1,
……
表达式n WHEN OTHERS;
选择值要覆盖所有可能情况,若不能一一指定,用OTHERS为其他情况找个出口;
选择值必须互斥,不能出现条件重复或重叠的情况。
4X1多路选择器
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
ENTITY MUX IS
PORT
( Data0,Data1,Data2,Data3:IN Std_Logic_VECTOR(7 DOWNTO 0);
Sel:IN Std_Logic_Vector(1 DOWNTO 0);
DOUT:OUT Std_Logic_Vector(7 DOWNTO 0)
);
END;
ARCHITECTURE DataFlow OF MUX IS
BEGIN
WITH Sel SELECT
DOUT<= Data0 WHEN “00”,
Data1 WHEN “01”,
Data2 WHEN “10”,
Data3 WHEN “11”,
“00000000” WHEN OTHERS;
END;
c. 条件信号赋值语句
赋值目标信号 <= 表达式1 WHEN 赋值条件1 ELSE
表达式2 WHEN 赋值条件2 ELSE
表达式n WHEN 赋值条件n ELSE
表达式;
各赋值语句有优先级的差别,按书写顺序从高到低排列;
各赋值条件可以重叠。
8输入优先编码器
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
ENTITY Priority_Encoder IS
PORT
( I:IN Std_Logic_VECTOR(7 DOWNTO 0);
A:OUT Std_Logic_Vector(2 DOWNTO 0)
);
END;
ARCHITECTURE DataFlow OF Priority_Encoder IS
BEGIN
A<= “111” WHEN I(7)=‘1’ ELSE
“110” WHEN I(6)=‘1’ ELSE
“101” WHEN I(5)=‘1’ ELSE
“100” WHEN I(4)=‘1’ ELSE
“011” WHEN I(3)=‘1’ ELSE
“010” WHEN I(2)=‘1’ ELSE
“001” WHEN I(1)=‘1’ ELSE
“000” WHEN I(0)=‘1’ ELSE
“111”;
END;
d. 进程语句
进程语句定义顺序语句模块,用于将从外部获得的信号值, 或内部的运算数据向其他的信号进行赋值。
进程本身是并行语句,但内部是顺序语句;
进程只有在特定的时刻(敏感信号发生变化)才会被激活。
[进程标号:] PROCESS //(敏感信号参数表)一个进程可以有多个敏感信号,任 一敏感信号发生变化都会激活进程
[声明区];//在进程中起作用的局部变量
BEGIN
顺序语句
END PROCESS [进程标号];
进程的工作原理
进程与时钟
在每个上升沿启动一次进程(执行进程内所有的语句)。
上升沿描述:Clock’ EVENT AND Clock=‘1’
下降沿描述:Clock’ EVENT AND Clock=‘0’
上升沿描述:rising_edge (Clock)
下降沿描述:falling_edge (Clock)
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
ENTITY FreDevider IS
PORT
( Clock: IN Std_logic;
Clkout: OUT Std_logic);
END;
ARCHITECTURE Behavior OF FreDevider IS
SIGNAL Clk: Std_Logic;
BEGIN
PROCESS (Clock) --将时钟作为进程的敏感信号
BEGIN
IF rising_edge (Clock) THEN
Clk<=NOT Clk; --在时钟上升沿执行Clk<=NOT Clk
END IF;
END PROCESS;
Clkout<=Clk;
END;
仿真波形:
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
ENTITY Counter IS
PORT
( RESET:IN Std_Logic; --异步复位信号
Clock: IN Std_logic; --时钟信号
NUM: BUFFER Integer RANGE 0 TO 3); --计数器输出值
END;
ARCHITECTURE Behavior OF Counter IS
BEGIN
PROCESS (RESET, Clock) --将复位、时钟作为进程的敏感信号
BEGIN
IF RESET=‘1’ THEN
Num<=0; --复位时Num清0 ELSIF rising_edge (Clock) THEN
IF Num=3 THEN
Num<=0; --如果Num=3就清0
ELSE
Num<=Num+1; -- 否则自加1 END IF;
END IF;
END PROCESS;
END;
仿真波形:
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
USE IEEE.Std_Logic_unsigned.ALL;
ENTITY Counter IS
PORT
( clr :IN Std_Logic;
inl: in std_logic_vector(3 downto 0);
outl: out std_logic_vector(3 downto 0) --计数器输出值
);
END;
ARCHITECTURE Behavior OF Counter IS
BEGIN
PROCESS (clr, inl) --进程的敏感信号
BEGIN
IF (clr=‘1’ or inl=“1001”) THEN
outl<=“0000”;
ELSE
outl<=inl+1; //重载符号,在库IEEE.Std_Logic_unsigned中预先声明
END IF;
END PROCESS;
END;
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
USE IEEE.Std_Logic_unsigned.ALL;
ENTITY Counter IS
PORT
( clr,clk:IN Std_Logic;
cnt: buffer std_logic_vector(3 downto 0) --计数器输出值
);
END;
ARCHITECTURE Behavior OF Counter IS
BEGIN
PROCESS
BEGIN
Wait until clk’event and clk=‘1’; //Wait语句,信号赋值有寄存功能,引入时序器件
IF (clr=‘1’ or cnt=9) THEN
cnt<=“0000”;
ELSE
cnt<=cnt+1;
END IF;
END PROCESS;
END;
进程的启动
当process的敏感信号参数表重没有列出任何敏感信号时,进程通过wait语句启动。
ARCHITECTURE Behavior OF state IS
BEGIN
PROCESS --敏感信号列表为空
BEGIN
wait until Clock; --等待clock激活进程
IF ( drive=‘1’) THEN
CASE output IS
WHEN s1 => output <= s2;
WHEN s2 => output <= s3;
WHEN s3 => output <= s4;
WHEN s4 => output <= s1;
END CASE;
END IF;
END PROCESS;
END;
进程注意事项:
进程本身是并行语句,但内部为顺序语句;
进程在敏感信号发生变化时被激活,在使用了敏感表的进程中不能含wait语句;
在同一进程中对同一信号多次赋值,只有最后一次生效;
在不同进程中,不可对同一信号进行赋值;
一个进程不可同时对时钟上、下沿敏感。
进程中的信号赋值是在进程挂起时生效的,而变量赋值是即时生效。
相对于结构体而言,信号具有全局性,是进程间进行并行联系的重要途径。
进程为综合器支持,且其建模方式直接影响仿真和综合结果,综合后对应于进程的硬件结构对进程中所有可读入信号都是敏感的。
元件例化语句
元件例化引入一种连接关系,将预先设计好的实体定义为元件,并将此元件(要插在电路系统板上的芯片)与当前设计实体中的端口(电路板上准备接受芯片的插座 )相连接,从而为当前设计(较大的电路系统)实体引入一个新的低一级的设计层次。
Component 元件名
port (端口名表);//列出对外通信的各端口名
End component 元件名;
例化名:元件名 port map ( [元件端口名=>]连接端口名 , …);
解析:
名字关联方式:port map语句中位置可以任意;
位置关联方式:端口名和关联连接符号可省去, 连接端口名的排列方式与所需例化的元件端口定义中的端口名相对应。
当前系统与准备接 入的元件对应端口相连 的通信端口。
元件例化:
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
ENTITY ord41 IS
PORT( a1, b1,c1, d1:IN Std_Logic;
z1: out std_logic);
END;
ARCHITECTURE ord41behv OF ord41 IS
BEGIN
COMPONENT nd2
PORT( a, b: IN Std_Logic;
c: out std_logic);
End COMPONENT;
SIGNAL x, y: STD_LOGIC;
BEGIN
u1:nd2 PORT MAP( a1, b1, x); --位置关联方式
u2:nd2 PORT MAP( a=>c1, c=>y, b=>d1); --名字关联方式
u3:nd2 PORT MAP( x, y, c=>z1); --混和关联方式
END;
设计2输入与非门:
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
ENTITY nd2 IS
PORT
( a, b:IN Std_Logic;
c: out std_logic);
END;
ARCHITECTURE nd2behv OF nd2 IS
BEGIN
y<=a NAND b;
END;
3.2 顺序语句
顺序语句仅出现在进程和子程序中。
顺序语句综合后,映射为实际的门电路,系统一上电,门电路开始工作。电路可实现逻辑上的顺序执行,实际上所有门电路是并行工作的。
赋值语句
流程控制语句
空操作语句
等待语句
子程序调用语句
返回语句
赋值语句
ENTITY TEST_Signal IS
PORT
( Reset, Clock: IN Std_logic;
NumA, NumB: OUT Integer RANGE 0 TO 255
);
END;
ARCHITECTURE TEST OF TEST_Signal IS
SIGNAL A, B: Integer RANGE 0 TO 255;
BEGIN
PROCESS (RESET,Clock)
VARIABLE C: Integer RANGE 0 TO 255;
BEGIN
IF RESET=‘1’ THEN
A<=0; B<=2;C:=0;
ELSEIF rising_edge(Clock)
THEN
C:=C+1;A<=C+1;B<=A+2;
END IF;
END PROCESS;
Num A<=A; NumB<=B;
END;
流程控制语句
IF语句:
IF 条件式 THEN
顺序语句
END IF;
IF 条件式 THEN
顺序语句
ELSE
顺序语句
END IF;
IF 条件式 THEN //有优先级
顺序语句
ELSEIF 条件式2
THEN
顺序语句
ELSE
顺序语句
END IF;
用IF语句描述组合逻辑电路时,务必涵盖所有的情况,否则综合后将引入锁存器!
ENTITY Encoder IS
PORT
( En: IN Std_logic;
I: IN Std_logic_Vetor(7 DOWNTO 0);
A: OUT Std_logic_Vetor(2 DOWNTO 0);
Idle: OUT Std_logic
);
END;
ARCHITECTURE Behavior OF Encoder IS
BEGIN
PROCESS (En, I)
BEGIN
IF En=‘1’ THEN
IF I(7)=‘1’ THEN
A<=“111”; Idle<=‘0’;
ELSIF IF I(6)=‘1’ THEN
A<=“110”; Idle<=‘0’; ELSIF IF I(5)=‘1’ THEN
A<=“101”; Idle<=‘0’;
ELSIF IF I(4)=‘1’ THEN
A<=“100”; Idle<=‘0’;
ELSIF IF I(3)=‘1’ THEN
A<=“011”; Idle<=‘0’;
ELSIF IF I(2)=‘1’ THEN
A<=“010”; Idle<=‘0’;
ELSIF IF I(1)=‘1’ THEN
A<=“001”; Idle<=‘0’;
ELSIF IF I(0)=‘1’ THEN
A<=“000”; Idle<=‘0’;
ELSE //引入ELSE, 否则综合器 将引入锁存
A<=“000”; Idle<=‘1’; END IF;
END PROCESS;
END;
不完整条件语句与时序电路:
ENTITY COMP_BAD IS
PORT( a1 : IN BIT;
b1 : IN BIT;
q1 : OUT BIT );
END ;
ARCHITECTURE one OF COMP_BAD IS
BEGIN
PROCESS (a1,b1)
BEGIN
IF a1 > b1 THEN q1 <= '1' ;
ELSIF a1 < b1 THEN q1 <= ‘0’ ; -- 未提及当a1=b1时,q1作何操作 END IF;
END PROCESS ;
END ;
综合结果:
完整条件语句:
ENTITY COMP_GOOD IS
PORT( a1 : IN BIT;
b1 : IN BIT;
q1 : OUT BIT );
END ;
ARCHITECTURE one OF COMP_GOOD IS
BEGIN
PROCESS (a1,b1)
BEGIN
IF a1 > b1 THEN q1 <= '1' ;
ELSE q1 <= '0' ;
END IF;
END PROCESS ;
END ;
CASE语句:
CASE 表达式 IS
WHEN 选择值[|选择值 ]=>顺序语句;
WHEN 选择值[|选择值 ]=>顺序语句;
……
WHEN OTHERS=>顺序语句;
END CASE;
选择值不可重复或重叠;
当CASE语句的选择值无法覆盖所有的情况时,要用OTHERS指定未能列出的其他所有情况的输出值;
LIBRARY IEEE;USE IEEE.Std_Logic_1164.ALL;ENTITY MUX IS
PORT
( Data0,Data1,Data2,Data3:IN Std_Logic_VECTOR(7 DOWNTO 0);
Sel:IN Std_Logic_Vector(1 DOWNTO 0);
DOUT:OUT Std_Logic_Vector(7 DOWNTO 0)
);
END;
ARCHITECTURE DataFlow OF MUX IS
BEGIN
CASE Sel IS
WHEN “00”=> DOUT<= Data0;
WHEN “01”=> DOUT<= Data1;
WHEN “10”=> DOUT<= Data2;
WHEN “11”=> DOUT<= Data3;
WHEN OTHERS => DOUT<=“00000000” ;
END CASE;
END PROCESS;
END;
LOOP语句:
[LOOP 标号:] FOR 循环变量 IN 循环次数范围 LOOP
顺序语句临时变量
仅在此END LOOPLOOP [LOOP 标号];
循环变量:临时变量,仅在此END LOOPLOOP [LOOP 标号];中有效,无需事先定义。
循环次数范围:….TO…. ….DOWNTO…..从初值开始,每执行完一次后递增(递减),直到终值 为止。
Sum:=0;
FOR i IN 0 TO 9 LOOP
Sum:=Sum+i;
END LOOP;
循环次数只能用具体数值表达,否则不可综合。
VARIABLE Length:Integer RANGE 0 TO 15;
……
FOR i IN 0 TO Length LOOP
……
END LOOP;
NEXT语句:
NEXT语句主要用在LOOP语句执行中有条件或无条件转向控制,跳向LOOP语句的起点。
NEXT [循环标号] [WHEN 条件];
① NEXT ;--无条件终止当前循环,跳回到本次循环LOOP语句处,开始下一次循环。
② NEXT LOOP 标号;--当有多重LOOP语句嵌套时,跳转到指定标号LOOP语句处,重新开始执行循环操作。
③ NEXT LOOP 标号 WHEN 条件表达式;--条件表达式为TRUE, 执行NEXT语句,进入跳转操作,否则向下执行。
EXIT语句:
EXIT语句主要用在LOOP语句执行中有条件或无条件内部 转向控制,跳向LOOP语句的终点,用于退出循环。当程序需要处理保护、出错和警告状态时,语句能提供一个快捷、简便的方法。
EXIT [循环标号] [WHEN 条件];
① EXIT ;--无条件从当前循环中退出。
② EXIT LOOP 标号;--程序执行退出动作无条件从循环标号所标明 的循环中退出。
③ EXIT LOOP 标号 WHEN 条件表达式;--条件表达式为TRUE,程序从当前循环中退出。
NULL语句:
NULL为空操作语句,一般用于CASE中,表示在某些情况下对 输出不作任何改变,隐含锁存信号。不能用于纯组合逻辑电路。
PROCESS (Clock)
BEGIN
IF rising_edge (Clock) THEN
……
CASE Sel IS
WHEN…
WHEN OTHERS=>NULL;
END CASE;
……
END IF;
END PROCESS;
WAIT语句:
在进程或过程中执行到WAIT语句时,程序将被挂起,并设 置好再次执行的条件。
WAIT [ON 信号表][UNTIL 条件表达式][FOR 时间表达式];
① WAIT ;--未设置停止挂起的条件,表示永远挂起。
② WAIT ON 信号表;--敏感信号等待语句,敏感信号的变化将结束 挂起,再次启动进程。
③ WAIT UNTIL 条件表达式;--条件表达式为中所含的信号发生变 化,且满足WAIT语句所设条件,则结束挂起,再次启动进程。
④ WAIT FOR 时间表达式;--超时等待语句,从执行当前的WAIT语 句开始,在此时间段内,进程处于挂起状态,超过这一时间段后,程序自动恢复执行。
3.3 配置语句
配置主要为顶层设计实体指定结构体,或为参与例化的元 件实体指定所希望的结构体 ,以层次方式来对元件例化做结构配置。
Configuration 配置名 of 实体名 is
配置说明
End 配置名;
为顶层设计实体指定结构体
Entity nand is
port ( a, b: in std_logic;
c: out std_logic );
End entity nand;
Architecture one of nand is
begin
c<=not (a and b);
End architecture one;
Architecture two of nand is
begin
c<=‘1’ when (a=‘0’) and (b=‘0’) else
‘1’ when (a=‘0’) and (b=‘1’) else
‘1’ when (a=‘1’) and (b=‘0’) else
‘0’ when (a=‘1’) and (b=‘1’) else
‘0’;
End architecture two;
Configuration second of nand is
for two
end for;
End second; Configuration first of nand is
for one
end for;
End first;
为参与例化的元件实体指定所希望的结构体 ,以层次方式来对元件例化做结构配置。
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
Entity rs is
port ( r, s: in std_logic;
q,qf: out std_logic );
End entity rs;
Architecture rsf of rs is
Component nand
PORT( a, b: IN Std_Logic;
c: out std_logic);
End Component;
BEGIN
u1:nand PORT MAP (a=>s, b=>qf, c=>q);
u2:nand PORT MAP ( a=>q, b=>r, c=>qf);
END rsf;
用实体nand构成更高层次设计实体中的元件,由配置语 句指定元件实体nand使用哪个结构体。
Configuration sel of rs is
for rsf
for u1,u2:nand
use entity work.nand (two);
end for;
end for;
End sel;
Day 3 就到这里,Day 4 继续开始状态机在VHDL中的实现。