VHDL必会基础代码二:时序逻辑电路

        时序逻辑电路是一种输出不仅与当前的输入有关,而且与其输出状态的原始状态有关的电路。相当于在组合逻辑的输入端加上了一个反馈输入,在其电路中有一个存储电路,可以将输出的状态保持住。由于时序逻辑电路,包含的存储电路,因此不能采用组合逻辑电路的描述方式,时序电路引进了现态和次态的概念。使用逻辑表达式进行描述。

1.1时序电路的分类

        按照触发器的动作特点,时序电路可分为同步时序逻辑电路和异步时序逻辑电路。

        同步时序逻辑电路:所有的存储元件都在时钟脉冲CP统一控制下,用触发器作为存储元件。只有一个“时钟信号”,所有的内部存储器,只会在时钟的边沿时候改变。几乎现在所有的时序逻辑都是“同步逻辑”。

        异步时序逻辑电路:最基础的储存元件是锁存器。锁存器可以在任何时间改变它的状态,依照其它的锁存器信号的变动,它们新的状态就会被产生出来。时序脉冲只接入了第一块触发器,异步动作。

1.2锁存器

        锁存器是一种电平敏感的寄存器,典型的例子有RS锁存器与D锁存器。

1.2.1RS锁存器

RS锁存器真值表
SRQQ'
0011
0101
1010
11QQ'
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY SR_latch2 IS
        PORT(S,R : IN STD_LOGIC;
            Q,Qbar : OUT STD_LOGIC);
END SR_latch2;

ARCHITECTURE behave OF SR_latch2 IS
BEGIN
    PROCESS(R,S)
        VARIABLE rs : STD_LOGIC_VECTOR(1 DOWNTO 0);
    BEGIN
        rs := R&S;
        case rs is
            when "00" =>Q<='1';Qbar<='1';
            when "01" =>Q<='1';Qbar<='0';
            when "10" =>Q<='0';Qbar<='1';
            when others =>null;
        end case;
    END PROCESS;
END behave;

1.2.2D锁存器

        D锁存器与RS锁存器类似,只是在功能上实现的目的不同。D锁存器通过条件涵盖不完整的if语句产生寄存器。【不完整的if语句产生时序逻辑电路;完整的if语句产生组合逻辑电路】

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY D_latch is
    PORT(D,En : IN STD_LOGIC;
        Q : OUT STD_LOGIC);
END D_latch;

ARCHITECTURE behave OF D_latch IS
BEGIN
    PROCESS(D,En)
    BEGIN
        IF(En='1') then Q<=D;
        END IF;
    END PROCESS;
END behave;

1.3触发器

        锁存器输入信号会影响输出,但触发器不会。触发器是指边沿触发的寄存器,常见的有D型、JK型、T型。在描述触发器前要注意时钟上升沿的描述

1.3.1D触发器

        当时钟上升沿到来时,把D的值赋给Q,之后保持不变。到下一个时钟上升沿到来时,再次把D的值赋给Q。

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY D_FF1 IS
    PORT(D,clk : IN STD_LOGIC;
        Q : OUT STD_LOGIC);
END D_FF1;

ARCHITECTURE behave OF D_FF1 IS
BEGIN
-----------方法一---------------
    PROCESS(clk)
    BEGIN
        IF(clk'event and clk='1') then Q<=D;
        END IF;
    END PROCESS;
END behave;
-----------方法一---------------

-----------方法二---------------
    PROCESS
    BEGIN
        wait until(clk='1');
        Q<=D;
    END PROCESS;
END behave;
-----------方法二---------------

-----------方法三---------------
PROCESS(clk)
BEGIN
    IF(CLK='1') THEN Q<=D;
    END IF;
END PROCESS;
END behave;
-----------方法三---------------

时钟边沿检测的三种方法

方法一:

        上升沿:clock'event and clock='1'=rising_edge(clk)

        下降沿:clock'event and clock='0'=falling_edge(clk)

        注意:if(clock'event and clock='1') 语句后面不存在else分支。当clock为STD_LOGIC类型时,也可以利用if(rising_edge(clk))或if(falling_edge(clk))进行时钟边沿检测。

方法二:

        利用WAIT语句启动进程,检测clock的上升沿。注意:WAIT语句不能和敏感参数表同时存在,且WAIT语句只能出现在PROCESS进程的第一句或最后一句。

方法三:

        使用PROCESS语句和IF语句相结合实现。当clock发生跳变的时候,启动PROCESS进程,而在执行IF语句时,满足clock='1'时才对Q进行赋值更新,所以相当于clock发生跳变且跳变为‘1’时,将D赋给Q,实际上就是D触发器的描述。

1.3.2带Q非的D触发器

信号法:定义中间信号

ARCHITECTURE sig OF D_FF IS
    SIGNAL state : STD_LOGIC;
BEGIN
    PROCESS(clock,reset)
    BEGIN
        if (reset='0') then
            state<='0';
        elsif(rising_edge(clock) then state<=D;
        END IF;
    END PROCESS;
    Q<=state;
    Qbar<=not state;
END sig;  

变量法:定义一个中间变量

ARCHITECTURE sig OF D_FF IS
BEGIN
    PROCESS(clock,reset)
        VARIABLE state : STD_LOGIC;
    BEGIN
        if (reset='0') then
            state:='0';
        elsif(rising_edge(clock) then state<=D;
        END IF;
        Q<=state;
        Qbar<=not state;
    END PROCESS;
END sig;  

注意:信号和变量的定义域和作用域不同,赋值符号也不同。在同一个进程之中对同一个信号进行多次赋值,只有最后一次有效。

信号和变量的使用区别
信号的赋值符号式"<="变量的赋值符号式“:="
信号具有全局特性变量具有局部特性
信号具有硬件特性变量具有软件特性
对信号进行赋值具有延迟特性

对变量进行赋值具有立即特性

1.4寄存器

        一个D触发器就是一位寄存器,如果需要多位寄存器,就要用多个D触发器构成。触发器个数可以通过在实体中设置一个类属常数GENERIC来根据情况更改位数。

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY reg IS
    GENERIC(n : natural :=4);
    PORT(D : IN STD_LOGIC_VECTOR(n-1 DOWNTO 0);
        clock,rst : IN STD_LOGIC;
        Q : OUT STD_LOGIC_VECTOR(n-1 DOWNTO 0));
END reg;

ARCHITECTURE behave OF reg IS
BEGIN
    PROCESS(clock,rst)
    BEGIN
        IF(rst='0') then Q<=(others =>'0');
        elsif rising_edge(clock) then Q<=D;
        END IF;
    END PROCESS;
END behave;

1.5移位寄存器

1.5.1串进并出的移位寄存器

        顾名思义,输入数组是按变量一个一个进来的,所以输入端口in是变量,而移位之后的输出out则是一个向量。此处输出数组是从高到低定义的,故数组要左移,则要从倒数第二个高位到最低位的右侧再并上新数组即可,此处注意数组定义时的高低位,结合画图很容易判断数组片选下标以及新变量的添加位置

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY  cjbc IS
    GENERIC(n : natural :=8);
    PORT(a,clk : IN STD_LOGIC;
        q : OUT STD_LOGIC_VECTOR(n-1 DOWNTO 0));
END cjbc;

ARCHITECTURE behave OF cjbc IS
BEGIN
    PROCESS(clk)
        VARIABLE reg : STD_LOGIC_VECTOR(n-1 DOWNTO 0);
    BEGIN
        if rising_edge(clk) then 
            reg := reg(n-2 downto 0)&a;--左移
            --reg:= a & reg(n-1 downto 1);--右移
        END IF;
        q<=reg;
    END PROCESS;
END behave;
        

1.5.2 16位串入串出移位寄存器

        串入串出说明输入、输出端口性质均为变量。此处使用元件COMPONENT和生成语句GENERATE的方法【非常常用】。

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY diff_logic IS
    PORT(d,clk : IN STD_LOGIC;
            q :OUT STD_LOGIC);
END diff_logic;

ARCHITECTURE behave OF diff_logic IS
BEGIN
    PROCESS(clk)
    BEGIN
        if(clk'event and clk='1') then q<=d;
        END IF;
    END PROCESS;
END behave;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY shift_16 IS
    PORT(a,clk : IN STD_LOGIC;
            b : OUT STD_LOGIC);
END shift_16;

ARCHITECTURE behave OF shift_16 IS
    COMPONENT diff_logic
        PORT (d,clk : IN STD_LOGIC;
                q : OUT STD_LOGIC);
    END COMPONENT;
    SIGNAL z:STD_LOGIC(0 TO 16);
BEGIN
    z(0)<=a;
    FOR i in 0 to 15 GENERATE
        diffx : diff PORT MAP(z(i),clk,z(i+1));
    END GENERATE;
    b<=z(16);
END behave;

1.5.3 8位并进串出移位寄存器

        输入端口并进为向量,输出端口串出为变量。

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY bc IS
    PORT(data_in : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
        clk,load : IN STD-LOGIC;
        data_out :OUT STD_LOGIC);
END bc;

ARCHITECTURE behave OF bc IS
    SIGNAL q : STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
    PROCESS(clk,load)
    BEGIN
        if load='1' then
            q<=data_in;
            data_out<='X';
        elsif(clk'event and clk='1') then
            for i in 1 to 7 loop
                q(i)<=q(i-1);
            END LOOP;
            data_out<=q(7);
        END IF;
    END PROCESS;
END behave;

1.5.4 8位并进并出双向移位寄存器

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY rlshift IS
    PORT(clr,lod,clk,s,dir,dil : IN BIT;
        d : IN BIT_VECTOR(7 DOWNTO 0);
        q : OUT BIT_VECTOR(7 DOWNTO 0));
END rlshift;

ARCHITECTURE behave OF rlshift IS
    SIGNAL q_temp : BIT_VECTOR(7 DOWNTO 0);
BEGIN
    PROCESS(clr,clk,lod,s,dir,dil)
    BEGIN
        IF clr='0' then q_temp<="00000000";
        ELSIF(clk'event and clk='1') then
            IF lod='1' then q_temp<=d;
            ELSIF(s='1') then
                FOR i in 7 downto 1 LOOP--实现右移操作
                    q_temp(i-1)<=q(i);
                END LOOP;
                q_temp(7)<=dir;
            ELSE
                FOR i in 0 to 6 LOOP--实现左移操作
                    q_temp(i-1)<=q(i);
                END LOOP;
                q_temp(0)<=dil;
            END IF;
        END IF;
        q<=q_temp;
    END PROCESS;
END behave;

1.6计数器

用“+”函数描述。此处‘+’是一个重载函数,需要调用IEEE.STD_LOGIC_UNSIGNED.ALL库。

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY counter IS
    GENERIC(n : natural :=4);
    PORT(clk,reset: IN STD_LOGIC;
        count : OUT STD_LOGIC_VECTOR(n-1 DOWNTO 0));
END counter;

ARCHITECTURE behave OF counter IS
BEGIN
    PROCESS(clk,reset)
        VARIABLE cnt : STD_LOGIC_VECTOR (n-1 DOWNTO 0);
    BEGIN
        if reset='1' then cnt := (others=>'0');
        elsif rising_edge(clk) then cnt:=cnt+1;
        END IF;
        count<=cnt;
    END PROCESS;
END behave;

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值