时序电路的ⅤHDL设计 Mealy状态机设计要点 设定若干状态; 用输入和状态控制进程 用case语句分别选择每一个状态; 用if语句确定输入条件,指定相应的下一状态和输出值 输出立即赋值(使用一个进程); 状态等待时钟条件满足再进行赋值(使用另一个进程) 例 Mealy状态机设计 该状态机具有4个状态,输入x,输出z;状态转换图如下所 /z 1/0 0/0 1/0 library ieee use ieee std logic 1164 all ity mealy is port(x,clk: in std le z: out std logic) end mealy architecture beh of mealy is type state is(sO, Sl, S2, $3); signal current state, next state: state
时序电路的 VHDL 设计 Mealy 状态机设计要点: 设定若干状态; 用输入和状态控制进程; 用 case 语句分别选择每一个状态; 用 if 语句确定输入条件,指定相应的下一状态和输出值; 输出立即赋值(使用一个进程); 状态等待时钟条件满足再进行赋值(使用另一个进程); 例 Mealy 状态机设计 该状态机具有 4 个状态,输入 x,输出 z;状态转换图如下所 示; 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
aaa process( current state, X case current state Is when s0=> if x=o' then z if xo' then z if xeo then z if x=o' then z<=o'. next state<=s3 else z<='l next state<=sl: end end process aaa sync process be wait until clk'event and clkel current state<=next state end process sync, end beh counter计数器 计数器通常以ck信号为基本输入,对输入信号进行计数: 在clk每个周期中改变一次计数器状态,状态可以输出; 经过n次计数后,计数器将回到初始状态,并给出进位输 出信号 计数器的ⅤHDL设计的要点在于正确安排状态的变化次 序,以及满足类型及运算的相容性; 例1p708表8-14
aaa:process(current_state,x) begin case current_state is when s0=> if x='0' then z if x='0' then z if x='0' then z if x='0' then z<='0';next_state<=s3; else z<='1';next_state<=s1; end if; end case; end process aaa; sync:process begin wait until clk'event and clk='1'; current_state<=next_state; end process sync; end beh; counter 计数器 计数器通常以 clk 信号为基本输入,对输入信号进行计数: 在 clk 每个周期中改变一次计数器状态,状态可以输出; 经过 n 次计数后,计数器将回到初始状态,并给出进位输 出信号; 计数器的 VHDL 设计的要点在于正确安排状态的变化次 序,以及满足类型及运算的相容性; 例 1 p.708 表 8-14
4位二进制加法计数器74163 具有同步复位,同步置数和进位控制功能 library ieee, use ieee std logic arith. all entity k74163 is port( clk, clrl, ldl, enp, ent: in std logic: d in unsigned (3 downto 0); g out unsigned (3 downto 0); rco: out std logic) end K74163 architecture beh of k74 163 is signal iq: unsigned (3 downto 0) process(clk, ent, iq) if clk'event and clk='l'then if clrl=o then iq0) elsif (ent and enp)='I then iq<=iq d if if(iq=15)and(ent=I")then rco<=l else rco<=O nd if end process end beh 将上述程序中的iq=iq-1,就构成减法计数器
4 位二进制加法计数器 74163 具有同步复位,同步置数和进位控制功能; 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 process (clk,ent,iq) begin if clk'event and clk='1' then if clrl='0' then iq'0'); elsif ldl='0' then iq<=d; elsif (ent and enp)='1' then iq<=iq+1; end if; end if; if (iq=15) and (ent='1') then rco<='1'; else rco<='0'; end if; q<=iq; end process; end beh; 将上述程序中的 iq<=iq-1,就构成减法计数器;
注意:对于 signed类型,在位数固定的条件下,加/减1的运 算可以自动产生循环,不会有进位或借位问题发生 若希望输入和输出都是 std logic类型,则可在程序中进 行如下变化 library ieee use ieee std logic 1164. all; use ieee std logic arith entity k74163 is port( clk, clrl,ldl, enp, ent: in std logic, d: in std logic vector(3 downto 0); g: out std logic vector (3 downto 0); rco: out std logic) end K74163 architecture beh of k74 163 is signal iq: unsigned (3 downto 0) process(clk, ent, ig) if clk'event and clke'I then if clrl=o' then iq0); elsif ldl=O' then iq<=unsigned(d) Isif(ent and enp)I' then iq<=iq+I end if end if if (iq=15)and(ent=I')then rco<='l else rco<=0 end process
注意:对于 usigned 类型,在位数固定的条件下,加/减 1 的运 算可以自动产生循环,不会有进位或借位问题发生; 若希望输入和输出都是 std_logic 类型,则可在程序中进 行如下变化: 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 std_logic_vector (3 downto 0); q: out std_logic_vector (3 downto 0); rco:out std_logic); end k74163; architecture beh of k74163 is signal iq: unsigned (3 downto 0); begin process (clk,ent,iq) begin if clk'event and clk='1' then if clrl='0' then iq'0'); elsif ldl='0' then iq<=unsigned(d); elsif (ent and enp)='1' then iq<=iq+1; end if; end if; if (iq=15) and (ent='1') then rco<='1'; else rco<='0'; end if; q<=iq+0; end process; end beh;
在p709表8-15中显示了余3码计数器,与74163相比,变 化为:只有10个状态(从3到12) 在状态12时输出进位信号 程序的改变只有两句: elseif (ent and enp)'I and (iq=12)then iq<=0011 if (iq=12)and(ent='I")then rco<=I 前一句指定加法循环的起点和终点;后一句指定进位信号 采用类似方案很容易构成任意进制的计数器: 计数器设计的一个关键问题在于电路综合的效果,很多 综合工具会将计数器的每一步(加1)作为一个加法器进行综 合,导致庞大的组合电路;为了避免出现这种情况,通常只 用上述方式构成小规模计数器,而对大规模计数器则采用结 构设计方式,由小规模计数器级连构成 例:16位加法二进制计数器的结构设计(模65536) 采用4个74163级连构成 library iee use ieee std logic 1164. all use ieee std logic arith. all entity kcount16 port( clk, clrl, ldl, en: in std log d: in unsigned (15 downto 0) q: out unsigned (15 downto 0) rco: out std logic)
在 p.709 表 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)作为一个加法器进行综 合,导致庞大的组合电路;为了避免出现这种情况,通常只 用上述方式构成小规模计数器,而对大规模计数器则采用结 构设计方式,由小规模计数器级连构成; 例: 16 位加法二进制计数器的结构设计(模 65536) 采用 4 个 74163 级连构成 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);
nd kcount16 architecture str of kcount16 is component k74 163 port( clk, clrl, ldl, enp, ent: in std logic; d in unsigned(3 downto 0) g out unsigned (3 downto O) rco: out std logic); signal co0, col, co2: Std logic, ul: k74163 port map (clk, clrl, ldl, en, en, d(3 downto 0),q(3 downto 0), co0); 2: k74163 port map (clk, clrl, ldl, co0, coo, d (7 downto 4), q(7 downto 4), col) u3: k74 163 port map (clk,clrl, ldl, col, col, d(ll downto 8), q(1l downto 8),co2) u4: k74163 port map (clk,clrl, ldl, co2, co2, d(15 downto 12), q(15 downto 12), rco); end 该计数器同样具有同步复位、同步置数等功能; 计数器的应用 作为时序电路的重要功能器件,计数器可以构成许多特 定的功能部件; 将时钟输入信号作为时间信号,则输入与输出之间可以 保持一种时间关系,利用这种关系,可以将计数器设计为定 时器,在电路中,每隔几个时钟周期就给出一个输出脉冲, 可用于规范电路中各功能块的执行时间(例如串-并数据转换 电路) 若将输入时钟信号设定为标准时间单位(例如ms、s)等 将计数器的模设置为满足相应的时间进位关系,则可以设 出各类计时工具,如电子秒表、电子钟等 采用模足够大的计数器,通过控制其使能端,使其在单
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 downto 12),rco); end str; 该计数器同样具有同步复位、同步置数等功能; 计数器的应用 作为时序电路的重要功能器件,计数器可以构成许多特 定的功能部件; 将时钟输入信号作为时间信号,则输入与输出之间可以 保持一种时间关系,利用这种关系,可以将计数器设计为定 时器,在电路中,每隔几个时钟周期就给出一个输出脉冲, 可用于规范电路中各功能块的执行时间(例如串-并数据转换 电路); 若将输入时钟信号设定为标准时间单位(例如 ms、s)等, 将计数器的模设置为满足相应的时间进位关系,则可以设计 出各类计时工具,如电子秒表、电子钟等; 采用模足够大的计数器,通过控制其使能端,使其在单
位时间对输入信号(clk)进行计数,则可以得到单位时间内 信号周期数,这正是数字频率计的基本设计思想 若考虑输入信号和输出信号的频率关系,则计数器本身 就是分频器,对于二进制计数器,各状态输出端分别输出对 应输入信号的2分频,如2分频、4分频、8分频等; 在实际数字电路中,通常用晶体振荡器为电路提供外部 参考时钟,该时钟频率极高,由于对于计数器模的设置可以 得到输入信号的任意整数分频,降低时钟频率,因而计数器 可以用于设计频率发生器(时钟信号发生器),为内部不同器 件提供不同的时钟信号 将计数器与二进制译码器结合,可构成顺序脉冲发生器 计数器与数据选择器结合,可构成序列信号发生器: Shift-Register移位寄存器 移位寄存器可以寄存n位二进制数(可以将其视为串行 排列的数组),在每个时钟周期,内部寄存数据移动1位(向 右或向左),同时有1位数据移入或移出 利用进程中简单的代入语句可以很方便地设计移位寄存 例1简单的4位右移移位寄存器; 功能要求:串行输入、串行输出 library iee use ieee std logic 1164. all; entity kshfregl is port( clk, d: in std logic; y: out std logic) nd kshfregl architecture beh of kshfregl is signal q0, q1, 2: std logic
位时间对输入信号(clk)进行计数,则可以得到单位时间内 信号周期数,这正是数字频率计的基本设计思想; 若考虑输入信号和输出信号的频率关系,则计数器本身 就是分频器,对于二进制计数器,各状态输出端分别输出对 应输入信号的 2n 分频,如 2 分频、4 分频、8 分频等; 在实际数字电路中,通常用晶体振荡器为电路提供外部 参考时钟,该时钟频率极高,由于对于计数器模的设置可以 得到输入信号的任意整数分频,降低时钟频率,因而计数器 可以用于设计频率发生器(时钟信号发生器),为内部不同器 件提供不同的时钟信号; 将计数器与二进制译码器结合,可构成顺序脉冲发生器; 将计数器与数据选择器结合,可构成序列信号发生器; Shift-Register 移位寄存器 移位寄存器可以寄存 n 位二进制数(可以将其视为串行 排列的数组),在每个时钟周期,内部寄存数据移动 1 位(向 右或向左),同时有 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;
if(clk'event and clk='1 )then go<=d; ql<=q0; q2<=q1; y<=q2 nd if: end 利用连接运算符号&,也可以将上述程序改为如下形式 architecture beh of kshfregl is signal q: std logic vector(0 to 2) proc if(clk 'event and clk='1 )then &q(0tol)y<=q(2) end it end process; end beh. 例2典型的8位移位寄存器 功能要求:可实现异步复位、同步置数(并行输入)状态输 出(并行输出)、串入串出的左右移控制; library iee use ieee std logic 1164. all; entity kshfreg2 is port( clk, dr, dI: in std logic dir clr.ld: in std logic ector(7 downto 0) q: out std logic vector(7 do end kshfreg 2
begin process(clk) begin if (clk'event and clk='1') then q0<=d; q1<=q0; q2<=q1; y<=q2; end if; end process; end beh; 利用连接运算符号&,也可以将上述程序改为如下形式: 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); end if; end process; end beh; 例2 典型的 8 位移位寄存器 功能要求:可实现异步复位、同步置数(并行输入)、状态输 出(并行输出)、串入串出的左/右移控制; library ieee; use ieee.std_logic_1164.all; entity kshfreg2 is port ( clk,dr,dl: in std_logic; dir,clr,ld: in std_logic; d:in std_logic_vector(7 downto 0); q:out std_logic_vector(7 downto 0)); end kshfreg2;
tecture beh of kshfreg2 is qi: std logic vector(7 downto O); process(clk, clr) if cIr'I'then qi0) elsif (clk' event and clk='I)then if ld='I' then qi<=d elsif dir=o' then qi<= qi(6 downto 0)& dr qi<=dl qi(7 downto 1); end if end it end process 对于上述程序进行适当改动,可以构成各种类型的功能器件。 移位寄存器的应用 利用串行输入并行输出,可以形成串并转换接口,接收 串行通信线路送来的信息;利用并行输入串行输出,可以形 成并串转换接口,将系统信息通过串行方式发送出去;串行 输入/串行输出可以作为延迟器,实现信号的延迟 在右移模式下,将内部信号d(⑦)赋值给d(0),就构成环 行计数器,在每个时钟周期,内部寄存数据循环右移1位; 同样可以设计循环左移的寄存器:循环移位寄存器的状态输 出可以构成简单的序列信号发生器或顺序脉冲发生器,在时
architecture beh of kshfreg2 is signal qi:std_logic_vector(7 downto 0); begin process(clk,clr) begin if clr='1' then qi'0'); elsif (clk'event and clk='1') then if ld='1' then qi<=d; 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; 对于上述程序进行适当改动,可以构成各种类型的功能器件。 移位寄存器的应用 利用串行输入并行输出,可以形成串-并转换接口,接收 串行通信线路送来的信息;利用并行输入串行输出,可以形 成并-串转换接口,将系统信息通过串行方式发送出去;串行 输入/串行输出可以作为延迟器,实现信号的延迟; 在右移模式下,将内部信号 di(7)赋值给 di(0),就构成环 行计数器,在每个时钟周期,内部寄存数据循环右移 1 位; 同样可以设计循环左移的寄存器;循环移位寄存器的状态输 出可以构成简单的序列信号发生器或顺序脉冲发生器,在时
钟信号驱动下,该电路在串行输出端输出周期性的序列信号, 或在并行输出端输出顺序脉冲信号 适当循环移位寄存器设置内部数据及反馈结构,可以构 成移位寄存型计数器,实现特定状态变化计数的功能,也可 以构成更为复杂的序列信号发生器;这种带反馈结构的移位 寄存型计数器可以作为伪随机信号发生器使用,在各类纠错 编码的设置中也经常采用这种结构(例如循环冗余校验器 CRC) 将串行输入端口接地,由并行输入/输出移位寄存器中的 数据,在一个时钟周期中,可以实现对寄存数据的乘2(右移) 或除2(左移)运算电路,在算术运算中发挥重要作用; 在8.10节(p743-746)中,还讨论了小型移位寄存器 的结构设计及其他一些类型的移位寄存器设计问题
钟信号驱动下,该电路在串行输出端输出周期性的序列信号, 或在并行输出端输出顺序脉冲信号; 适当循环移位寄存器设置内部数据及反馈结构,可以构 成移位寄存型计数器,实现特定状态变化计数的功能,也可 以构成更为复杂的序列信号发生器;这种带反馈结构的移位 寄存型计数器可以作为伪随机信号发生器使用,在各类纠错 编码的设置中也经常采用这种结构(例如循环冗余校验器 CRC); 将串行输入端口接地,由并行输入/输出移位寄存器中的 数据,在一个时钟周期中,可以实现对寄存数据的乘 2(右移) 或除 2(左移)运算电路,在算术运算中发挥重要作用; 在 8.5.10 节(p.743—746)中,还讨论了小型移位寄存器 的结构设计及其他一些类型的移位寄存器设计问题