VHDL语法入门 (四) 并行与串行

1.并发代码

VHDL代码按照执行顺序可以分为并发代码和顺序代码,即并行与串行

并发描述语句有when和generate,此外,仅包含and,not,+,*和sll等操作符的赋值语句也是并发执行的。在块(block)中的代码也是并发执行的

1.1when语句

when语句分为when/else(又称simple when)和when/select/when(又称select when)两种

--when/else
assignment when condition else
assignment when condition else
...;

--when/select/when
assignment when value,
assignment when value,
...;


--例
--when/else
outp <= "000" when (inp = '0' or reset = '1') else
        "001" when ctl ='1' else
        "010";
        
--when/select/when
--当使用with/select/when时,必须对所有可能出现的条件(condition)予以考虑,所以常使用关键字others。
with control select
    output <= "000" when reset,
        "111" when set,
        unaffected when others;    --如果在某些条件出现时不需要进行任何操作,可以使用UNAFFECTED
        
--当需要对多种情况进行判断时,when value的描述方式包括以下3种
when value    --针对单个值进行判断
when value1 to value2    --针对取值范围进行判断,使用枚举类型
when value1 | value2 | ...    --针对多个值进行判断

1.2generate语句

generate是另一种基本的并发现描述语句,它和顺序描述语句中的loop语句一样用于循环执行某项操作,通常与for一起使用

语法结构

--for/generate
label: for identifier in range generate
    (condition, assignment)
end generate

--if/generate
--if/generate不允许使用else,可以与for/generate嵌套使用
label1: for idnetifier in range generate
    ...
    label2: if condition generate
        (condition assignment)
    end generate;
    ...
end generate;

--例
signal x: bit_vector(7 downto 0);
signal y: bit_vector(15 downto 0);
signal z: bit_vector(7 downto 0);
...
g1: for i in x'range generate
    z(i) <= x(i) and y (i+8);
end generate

generate中循环的上界和下界必须是静态的,如果上界或下界中的参数是非静态的,那么代码通常不可综合

1.3块语句

块语句分为简单块(simple block)和卫式块(guarded block)

simple block

simple block仅仅是一种对原有代码进行区域分割的方式

----------法结构如下----------
label: block
    [declarative part]
begin
    (concurrent statement)
end block label;


----------一个完整的block----------
b1: block
    signal a: std_logic;
begin
    a <= input_sig when ena = '1' else 'z';
end block b1;


----------利用block对构造体进行规整----------
architecture example ...
begin
    ...
    block1: block
    begin
        ...
    end block block1;
    ...
    block2: block
    begin
        ...
    end block block2;
    ...
end example;


----------simple block 与 guarded block可以相互嵌套----------
label1: block
    [顶层block部分声明]
begin
    (顶层block并发描述语言)
label2:block
    [嵌套block部分声明]
begin
    (嵌套block并发描述语言)
end block label2;
    (顶层block其他并发描述语言)
end block label2;

guarded block

guarded block 与simple block 相比,多了一个卫式表达式。只有当卫式表达式值为真时,在guarded block中前面有关键词guarded的语句才会执行

语法结构如下

label: block(卫式表达式)
    [声明部分]
begin
    (卫式语句和其他并发描述语句)
end block label;

2.顺序代码

VHDL本质都是并发执行的代码,但是在PROCESS,FUNCTION和PROCEDURE内部的代码都是顺序执行的。当作为一个整体时,他们与外部的其他代码之间又都是并发执行的。

变量只能在顺序代码中使用,相对于信号而言,变量只能时局部的,所以他的值不能传递到process,function和procedure外部

2.1进程

进程(process)内部的语句是一种顺序描述语句,其内部经常使用if,wait,case或loop语句。

process具有敏感信号列表(sencitivity list),或者使用wait语句进行执行条件的判断。process必须包含在主代码段,当敏感信号列表中某个信号发生变化时(或当wait条件语句得到满足时),process内部代码就顺序执行一次。其语法结构如下

[label:]process (sensitivity list)
    [variable name: type [range][:= initial_value;]]
begin
    (顺序执行的代码)
end process [label];

其中变量声明部分是可选的,如果要process内部使用变量,则必须在关键字begin之前的变量声明部分对其进行定义。变量的初始值是不可综合的,只是在仿真过程中使用。

label也是可选的,使用label可增加代码的可读性。

2.2信号和变量

为了方便理解后面的内容,这里补充一点信号与变量的知识,信号与变量详细的讲解会在之后发布

在VHDL中,有两种方法进行动态的数值传递:信号和变量。其中,信号可以在package,entity和architecture中声明,而变量只能在一段顺序描述的代码中声明(比如在process内部进行信号声明)。因此,信号通常是全局的,而变量通常是局部的。

变量的值无法传递到process外的,如果需要进行变量值的传递,必须先把这个值赋给一个信号,然后由该信号将值传递到process外部。赋予变量的值是立即生效的,在此后的代码中,此变量将使用新的变量值。这一点和process中使用的信号不同,新的信号值通常只有在整个process运行完毕以后才开始生效。

2.3if语句

语法结构

if condition then assignments;
elsif conditions then assifnments;
...
else assignments;
end if;


--例
if (x<y) then temp := "11111111";
elsif (x=y and w='0') then temp := "11110000";
else temp := (other => '0');
end if;

2.4wait语句

如果process中使用了wait语句,就不能在使用敏感信号列表了。语法结构如下

--直到信号条件(signal_condition)满足时才进行后面的操作
--在使用wait until时,由于process没有敏感信号列表,所以它必须时process中的第一条语句
wait until signal_condition;
--当后面列出的信号有一个发生变化时,开始进行后面的操作
wait on [signal1,signal2,...];
--等待time所确定的时间后才开始进行后面的操作
wait for time;


--例
process    --没有敏感信号列表
begin
    wait until (clk'event and clk = '1');
    if (rst = '1') then
        output <= "00000000";
    elsif (clk'event and clk = '1')then
        output <=input;
    end if;
end process;

2.5case语句

语法结构

case 表达式 is
    when 条件表达式 => 顺序执行语句;
    when 条件表达式 => 顺序执行语句;
    ...
end case;


--例
case control is
    when"00" => x <= a; y <= b;
    when"01" => NULL;    --等同于unaffected,表示没有任何操作
    when others => x <= "0000"; y <= "zzzz";
end case;

case语句允许在每个测试条件下执行多个赋值操作,而when语句只允许执行一个赋值操作

case与when语句对比

when

case

代码类型

并发代码

顺序代码

用法

在process,function和procedures外使用

在process,function和procedures内使用

必须列出所有可能的组合

是(对with/select/when来说)

每个判断分支允许的最大赋值操作数量

1

任意

没有操作动作时使用的关键字

unaffected

null

--下面两端代码实现了同样的功能
--when语句
with sel select
    x <= a when "000";
         b when "001";
         c when "010";
         unaffected when others;
         

--case语句
case sel is 
    when "000" => x <= a;
    when "001" => x <= b;
    when "100" => x <= c;
    when others => null;
end case

2.6loop语句

语法结构

--for/loop,循环固定次数
--与generate语句相似,for/loop语句中上下界必须是静态值,否则可能不可综合
[label:] for 循环变量 in 范围 loop
    (顺序描述语句)
end loop [label];

--while/loop,循环执行直到条件不再满足
[label:] while 条件表达式 loop
    (顺序描述语句)
end loop [label];

--exit,结束整个循环
[label:] exit [label] [when条件表达式];

--next,跳出本次循环
[label:] next [loop_label] [when条件表达式];


--例
 for i in 0 to 5 loop
     x(i) <= enable and w(i+2);
     y(0,i) <= w(i);
 end loop;

 3.实例

3.1用guard block实现D触发器

用guard block实现一个带复位,上升沿触发的D触发器

library ieee;
use ieee.std_logic_1164.all;

entity dff is
    port(d,clk,rst: in std_logic;
        q: out std_logic);
end dff;

architecture dff of dff is
begin
    b1: bolck(clk'event and clk = '1')
    begin
        q <= guard '0' when rst = '1' else d;    //卫式语句,当卫士表达式位真,即rst为1时,q输出0,负责输出d值。
    end block b1;
end dff;

3.2RAM模块

下面代码实现一个简易伪双端口RAM模块

library ieee;
use ieee.std_logic_1164.all;

entity ram is 
    generic(bits: integer := 8;
            words: integer := 16);
    port(wr_ena,clk; in std_logic;
         addr: in integer range 0 to words-1;
         data_in: in std_logic_vector(bits-1 downto 0);
         data_out: out std_logic_vector(bits-1 downto 0));
end ram;
 
architecture ram of ram is 
    type vector_array is array(0 to words-1) of std_logic_vector(bits-1 downto 0);
    signal memory: vector_array;
begin
    process (clk,wr_ena)
    begin
        if(wr_ena = '1')then
            if(clk'event and clk = '1')then
                memory(addr) <= data_in;
            end if;
        end if
    end process;
    data_out <= memory(addr);
end ram;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值