时序电路的结构与特点有限状态机 FSM的设计根据输出函数的形式,可以分为 moore机和
mealy机两类。
FSM的表达形式通常采用状态转换图表达电路信号的变化:
Moore,y = f(s) Mealy,y = f(s0,x)
FSM的设计要点定义枚举类型表达不同的状态特点;
设置信号表达现有状态和转换的状态;
对每一个现态,利用选择语句,根据控制条件 x决定转换次态 ;
根据现态和 x决定输出 y。
Moore机设计:例 1
例 1 简单的 Moore状态机设计状态转换图如下所示,要求设置 reset控制,
能直接使状态处于 s0。
library ieee;
use ieee.std_logic_1164.all;
entity statmach is
port(clk,input,reset,in std_logic;
output,out std_logic);
end statmach;
Moore机设计:例 1
architecture beh of statmach is
type state_type is (s0,s1);
--采用枚举法设置状态
signal st,state_type;
--表达当前的状态
begin
process(clk) --设置时钟控制模块
begin
if reset='1' then st<=s0;--异步复位
elsif clk'event and clk='1' then --边沿检测
Moore机设计:例 1
case st is --根据现态决定下一状态
when s0 => st<=s1;
when s1 => if input='1' then st<=s0;
end if;
end case;
end if;
end process;
output<='1' when st=s1 else'0';
--根据状态决定输出
end beh;
Moore机设计:例 1
例 2 Moore状态机的设计该状态机有 5个状态,转换图如下所示:其中输入控制 ID为 4位二进制数,在图中表达为 16
进制数;
Moore机设计:例 2
library ieee;
use ieee.std_logic_1164.all;
entity moore2 is
port(clk,rst,in std_logic;
id,in std_logic_vector(3 downto 0);
y,out std_logic_vector(1 downto 0));
end moore2;
Moore机设计:例 2
architecture beh of moore2 is
signal st,std_logic_vector(2 downto 0);--状态表达
--各状态命名并根据输出的特点进行赋值
constant s0:std_logic_vector(2 downto 0):="000";
constant s1:std_logic_vector(2 downto 0):="010";
constant s2:std_logic_vector(2 downto 0):="011";
constant s3:std_logic_vector(2 downto 0):="110";
constant s4:std_logic_vector(2 downto 0):="111";
begin
Moore机设计:例 2
process(clk,rst) --状态转移关系
begin
if rst='1' then st<=s0; --异步复位
elsif clk'event and clk='1' then --时钟边沿判断
case st is
when s0=> if id=x"3" then st<=s1;
else st<=s0;
end if;
when s1=> st<=s2;
when s2=> if id=x"7" then st<=s3; end if;
Moore机设计:例 2
when s3=> if id=x"7" then st<=s0;
elsif id=x"9" then st<=s4;
end if;
when s4=> if id=x"b" then st<=s0; end if;
when others=>st<=s0;
end case;
end if;
end process;
y<=st(1 downto 0); --输出方程
end beh;
Moore机设计:例 2
例 3 简单状态机设计 ( 教材 7.4 /9.2.1)
初始态,z=0
连续 2个触发沿 A=1,则 z=1;
若 z=1且 b=1,则 z保持 1。
Moore机设计:例 3
例 3 简单状态机设计 ( 教材 7.4 /9.2.1)
Moore机设计:例 3
architecture beh of smexamp is
type sreg_type is (init,a0,a1,ok0,ok1);
signal sreg:sreg_type;
begin
process(clk)
begin
if clk'event and clk='1' then
case sreg is
when init => if a='0' then sreg<=a0;
elsif a='1' then sreg<=a1;
end if;
Moore机设计:例 3
when a0 => if a='0' then sreg<=ok0;
elsif a='1' then sreg<=a1;
end if;
when a1 => if a='0' then sreg<=a0;
elsif a='1' then sreg<=ok1;
end if;
when ok0 => if a='0' then sreg<=ok0;
elsif a='1' and b='0' then sreg<=a1;
elsif a='1' and b='1' then sreg<=ok1;
end if;
Moore机设计:例 3
when ok1 => if a='0' and b='0' then sreg<=a0;
elsif a='0' and b='1' then sreg<=ok0;
elsif a='1' then sreg<=ok1;
end if;
when others =>sreg<=init;
end case;
end if;
end process;
Moore机设计:例 3
with sreg select --根据状态决定输出
z<= '0' when init|a0|a1,
'1' when ok0|ok1,
'0' when others;
end beh;
综合结果如下:
Moore机设计:例 3
通过对状态图的分析,可以简化:
使用 1个寄存器专门存放触发时的输入 a;
则状态可以减少到 3个;结构也简化了。
Moore机设计:例 4
architecture beh of smexamp is
type sreg_type is (init,looking,ok);
signal sreg:sreg_type;
signal lasta:std_logic;
begin
process(clk)
begin
if clk'event and clk='1' then
lasta<=a;
Moore机设计:例 4
case sreg is
when init => sreg<=looking;
when looking => if a=lasta then sreg<=ok;
else sreg<=looking;
end if;
when ok => if b='1' then sreg<=ok;
elsif a=lasta then sreg<=ok;
else sreg<=looking;
end if;
when others =>sreg<=init;
end case;
Moore机设计:例 4
end if;
end process;
with sreg select
z<= '1' when ok,
'0' when others;
end beh;
Moore机设计:例 4
FSM的设计,Mealy机设计要点:
用输入和状态控制进程;
用 case语句分别选择每一个状态;
用 if语句确定输入条件,指定相应的下一状态和输出值;
输出立即赋值(使用一个进程);
状态等待时钟条件满足再进行赋值(使用另一个进程);
例 Mealy状态机设计该状态机具有 4个状态,输入 x,输出 z;状态转换图如下所示;
Mealy机设计:例 1
library ieee;
use ieee.std_logic_1164.all;
entity mealy is
port(x,clk,in std_logic;
z,out std_logic);
end mealy;
architecture beh of mealy is
type state is (s0,s1,s2,s3);--设置状态类型
signal current_state,next_state,state;
--现态与次态
begin
Mealy机设计:例 1
aaa:process(current_state,x) --决定次态和输出
begin
case current_state is
when s0=> if x='0' then
z<='0';next_state<=s0;
else z<='1';next_state<=s2;
end if;
when s1=> if x='0' then
z<='0';next_state<=s0;
else z<='0';next_state<=s2;
end if;
Mealy机设计:例 1
when s2=> if x='0' then
z<='1';next_state<=s2;
else z<='0';next_state<=s3;
end if;
when s3=> if x='0' then
z<='0';next_state<=s3;
else z<='1';next_state<=s1;
end if;
end case;
end process aaa; --这个进程与时钟无关
Mealy机设计:例 1
sync:process --将现态转移为次态
begin
wait until clk'event and clk='1';
current_state<=next_state;
end process sync;
--这个进程受时钟控制
end beh;
Mealy机设计:例 1
计数器 (counter)设计计数器也称为分频器,是数字电路中的基本时序模块;
计数器通常以 clk信号为基本输入,对输入信号进行计数,在 clk每个周期中改变一次计数器状态,状态可以输出;
经过 n次计数后,计数器将回到初始状态,
并给出进位输出信号;
计数器的 VHDL设计可以采用两种方式:
1 采用二进制串设置状态,指定循环的起点和终点,在时钟触发条件下对状态进行加 1或减 1运算,使状态顺序变化;
2 采用结构设计方式,先形成小型计数器,
再扩展形成大型的计数器。
计数器 (counter)设计计数器的行为设计,74163
4位二进制加法计数器 74163 p.708 表 8-14
具有同步复位,同步置数和进位控制功能;
采用 unsigned数据类型进行设计;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity k74163 is
port ( clk,clrl,ldl,enp,ent,in std_logic;
d,in unsigned (3 downto 0);
q,out unsigned (3 downto 0);
rco:out std_logic);
end k74163;
architecture beh of k74163 is
signal iq,unsigned (3 downto 0);
begin
计数器的行为设计,74163
process (clk,ent,iq)
begin
if clk?event and clk=?1? then --时钟沿检测
if clrl='0' then iq<= (others=>'0');
--同步复位
elsif ldl=?0? then iq<=d;--同步置数
elsif (ent and enp)='1' then iq<=iq+1;
--状态按顺序改变
end if;
end if;
计数器的行为设计,74163
if (iq=15) and (ent='1') then rco<='1';
else rco<='0';
end if;
q<=iq;
end process;
end beh;
对于 usigned类型,在位数固定的条件下,加 1
或减 1的运算可以自动产生循环,不需要考虑起点和终点设置问题。
计数器的行为设计,74163
计数器的行为设计电路的综合与仿真结果:
在教材表 8-15 中显示了余 3码计数器,与
74163相比,变化为:只有 10个状态(从 3到 12)
在状态 12时输出进位信号;
对上述程序只需要改变两句:
elseif (ent and enp)='1' and (iq=12) then
iq<=“0011”; --现态为终态时,次态为初态
if (iq=12) and (ent=?1?) then rco<= '1?
--在终态输出 1
计数器的行为设计,BCD码计数器计数器的结构设计利用 4个 k74163连接成 16位加法二进制计数器(模 65536)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity kcount16 is
port ( clk,clrl,ldl,en,in std_logic;
d,in unsigned (15 downto 0);
q,out unsigned (15 downto 0);
rco:out std_logic);
end kcount16;
计数器的结构设计
architecture str of kcount16 is
component k74163
port ( clk,clrl,ldl,enp,ent,in std_logic;
d,in unsigned (3 downto 0);
q,out unsigned (3 downto 0);
rco:out std_logic);
end component;
signal co0,co1,co2:std_logic;
begin
计数器的结构设计
u1,k74163 port map
(clk,clrl,ldl,en,en,d(3 downto 0),
q(3 downto 0),co0);
u2,k74163 port map
(clk,clrl,ldl,co0,co0,d(7 downto 4),
q(7 downto 4),co1);
u3,k74163 port map
(clk,clrl,ldl,co1,co1,d(11 downto 8),
q(11 downto 8),co2);
u4,k74163 port map
(clk,clrl,ldl,co2,co2,d(15 downto 12),
q(15 downto12),rco);
end str;
关于正负边沿同时触发的问题在一些特殊的电路中,需要同时使用时钟的正负边沿进行触发。
在 VHDL设计中,可以采用两个进程分别处理正边沿触发和负边沿触发,形成两个不同的信号,然后再考虑怎么将两个信号合成最终输出。
关于正负边沿同时触发的问题例 1:时钟边沿计数器要求对时钟信号的正负边沿同时进行计数;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity clkcount is
port(clk,in std_logic;
y:out unsigned(7 downto 0) );
end clkcount;
关于正负边沿同时触发的问题
architecture beh of clkcount is
signal c1,c2:unsigned(7 downto 0);
begin
process(clk)
variable id,unsigned(7 downto
0):="00000000";
begin
if (clk'event and clk='1') then
id:=id+1; --上升沿计数
end if;
c1<=id;
end process;
关于正负边沿同时触发的问题
process(clk)
variable id,unsigned(7 downto
0):="00000000";
begin
if (clk'event and clk='0') then
id:=id+1; --下降沿计数
end if;
c2<=id;
end process;
y<=c1+c2;--将两个计数相加
end beh;
关于正负边沿同时触发的问题电路综合及仿真结果:
关于正负边沿同时触发的问题有时将运算得到的信号与时钟信号进行
“与”运算,也能使输出信号在时钟的两个边沿都发生变化;这对于某些特殊的信号发生器设计具有意义。
例 2:将模 3计数器的输出与时钟信号进行运算,可以得到以下结果:
关于正负边沿同时触发的问题
y1<=yi and clk;
y2<=yi and not clk;
y3<=yi xor clk;
考察 y3信号的上升沿,可以认为该信号是对时钟信号的 1.5分频( 半整数分频 )!
Shift-Register 移位寄存器设计移位寄存器可以寄存 n位二进制数(可以将其视为串行排列的数组),在每个时钟周期,内部寄存数据移动 1位(向右或向左),
同时有 1位数据移入或移出;
利用进程中简单的赋值语句可以很方便地设计移位寄存器;
移位寄存器设计:简单 4位右移
library ieee;
use ieee.std_logic_1164.all;
entity kshfreg1 is
port ( clk,d,in std_logic; y:out std_logic);
end kshfreg1;
architecture beh of kshfreg1 is
signal q0,q1,q2:std_logic;--中间信号
begin
移位寄存器设计:简单 4位右移
process(clk)
begin
if (clk'event and clk='1') then
q0<=d; q1<=q0; q2<=q1; y<=q2;
--注意信号赋值的意义
end if;
end process;
end beh;
移位寄存器设计:简单 4位右移利用连接运算符号 &,也可以将上述程序改为如下形式:
architecture beh of kshfreg1 is
signal q:std_logic_vector(0 to 2);
begin
process(clk)
begin
if (clk'event and clk='1') then
q<=d & q(0 to 1); y<=q(2);-- &实现数据 q右移
end if;
end process;
end beh;
移位寄存器设计,8位多功能器件可实现异步复位、同步置数(并行输入)、
状态输出(并行输出)、串入串出的左 /右移控制;
移位寄存器设计,8位多功能器件
library ieee;
use ieee.std_logic_1164.all;
entity kshfreg2 is
port ( clk,in std_logic;--时钟
dir,clr,ld,dr,dl,in std_logic;--各种控制信号
d:in std_logic_vector(7 downto 0);--并行输入
q:out std_logic_vector(7 downto 0));--并行输出
end kshfreg2;
移位寄存器设计,8位多功能器件
architecture beh of kshfreg2 is
signal qi:std_logic_vector(7 downto 0);
--内部传递信号
begin
process(clk,clr)
begin
if clr=?1? then qi<=(others=>?0?);--异步置零
elsif (clk'event and clk='1') then --时钟控制
if ld=?1? then qi<=d;--并入控制移位寄存器设计,8位多功能器件
elsif dir=?0? then --右移控制
qi<= qi(6 downto 0) & dr;
else --左移控制
qi<=dl & qi(7 downto 1);
end if;
end if;
q<=qi; --并行输出
end process;
end beh;
移位寄存器设计,8位多功能器件电路综合结果: