任意波形的函数发生器的设计
杨阳
赵星
刘超
本文采用的是一个三位的多路选择器来控制输出波形即输入端口 selo,分别是 0 的时候输出
的是递增波形,1 的时候输出是递减波形,2 的时候输出是三角波输出,3 的时候是阶梯波,
4 的时候是输出正弦波,5 的时候输出的是阶梯波。其整体的框架图(综合的寄存器级传输
逻辑)如下图所示
整体框架图
Clk0 是时钟控制端,reset0 复位控制端。
U2 是递增模块
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity zeng is
port (clk,reset:in std_logic;
Q:out std_logic_vector (7 downto 0));
end zeng;
architecture zeng_arc of zeng is
begin
process(clk,reset)
variable tem: std_logic_vector (7 downto 0);
begin
if reset='0'then
tem:=(others=>'0');
复位
实体定义
结构体定义
elsif clk'event and clk='1' then 当 一 个 上 升 时 钟 边 沿 来 临 是 执 行 递 增 操 作
(tem=tem+1)。
当记满到 255 是对各位数置零操作
if tem="11111111"then
tem:=(others=>'0');
else tem :=tem+1;
end if;
end if;
Q<=tem;
end process;
end zeng_arc;
如图所示 selo 是 0 选择的是输出 U2 模块的波形,前半部分可见是递增的波形
如上如所示当在 12.78us 时候计数达到 255 给各位置零开始下一个周期
U3 是递减波形的发生模块
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity jian is
port (clk,reset:in std_logic;
Q:out std_logic_vector (7 downto 0));
end jian;
architecture jian_arc of jian is
begin
process(clk,reset)
variable tem :std_logic_vector (7 downto 0);
begin
if reset='0'then
tem:="11111111";
elsif clk'event and clk='1' then
if tem="00000000"then
tem:="11111111";
else tem :=tem-1;
end if;
end if;
Q<=tem;
end process;
end jian_arc;
当一个时钟上升边沿来临时 tem 执行的是递减
的操作。
Selo 等于 1 选择 u3 的模块输出递减波形如上图所示从第一个上升沿开始给计数器的各位全
部置 1 最大值为 255,依次递减。
当时钟到达 12.74us 是递减到 0,开始下一个周期的递减给计数器的各位全部置 1 。
U4 是三角波的发生模块
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity delta is
port (clk,reset:in std_logic;
Q:out std_logic_vector (7 downto 0));
end delta;
architecture delta_arc of delta is
begin
process(clk,reset)
variable tem: std_logic_vector(7 downto 0);
variable a:std_logic;
%递增递减控制参数当 a=1 时候递减 tem=tem-1,
a=0 时候是递模式增 tem=tem+1 。
%%控制递增
%%控制递减
begin
if reset='0'then
tem:=(others=>'0');
elsif clk'event and clk='1'then
if a='0'then
if tem="11111110"then
tem:="11111111";
a:='1';
else
tem:=tem+1;
end if;
else
if tem="00000001"then
tem:=(others=>'0');
a:='0';
else
tem:=tem-1;
end if;
end if;
end if;
Q<=tem;
end process;
end delta_arc;
如图 selo 的数字是 2 选择的是 u4 模块三角波的输出。
时间到达 12.71us 时候 a 从 1 变到 0 开始递减运算。
时间到达 25.46us 时候 a 从 0 变成 1,再次进入递增状态开始新的一个周期。
U5:阶梯波形发生模块
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ladder is
port (clk,reset:in std_logic;
Q:out std_logic_vector (7 downto 0));
end ladder;
architecture ladder_arc of ladder is
begin
process(clk,reset)
variable tem: std_logic_vector(7 downto 0);
variable a:std_logic;
begin
if reset='0'then
tem:=(others=>'0');
elsif clk'event and clk='1'then
if a='0'then
%参数 a 用来做为周期控制
%当递增到 255 时候计数器再次置零。
if tem="11111111"then
tem:="00000000";
a:='1';
else
tem:=tem+16; %实现阶跃性加法操作每次递增为 16
a:='1';
%将每次的加法运算延迟一个周期
%将每次的加法运算延迟一个周期
end if;
else
a:='0';
end if ;
end if ;
Q<=tem;
end process;
end ladder_arc;
如图所示正如代码所预期的一样在 80ns 时候将加法运算延迟以后周期在此时 a 从 1 变成 0
等待下一个时钟上升沿的出现
在时间到达 139us 时候由于 240 加上 16 超出计数器的计数范围将计数器的所有位进行置 0
操作。开始下一个周期的阶跃递增操作。
U6:正弦波发生器模块 ,采用是真值表的编写方法
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity sin is
port(clk,clr:in std_logic;
d: out integer range 0 to 255);
end sin;
architecture sin_arc of sin is
begin
process(clk,clr)
variable tem : integer range 0 to 63;
begin
if clr='0'then
d<=0;
elsif clk'event and clk='1'then
if tem=63 then
tem:=0;
else tem:=tem+1;
%相当于控制地址的地址加法器。
%相当于存储数据的 rom 一共存放的是 64 个数。
end if ;
case tem is
when 00=>d<=255;when 01=>d<=254;when 02=>d<=252;
when 03=>d<=249;when 04=>d<=245;when 05=>d<=239;
when 06=>d<=233;when 07=>d<=225;when 08=>d<=217;
when 09=>d<=207;when 10=>d<=197;when 11=>d<=186;
when 12=>d<=174;when 13=>d<=162;when 14=>d<=150;
when 15=>d<=137;when 16=>d<=124;when 17=>d<=112;
when 18=>d<=99; when 19=>d<=87; when 20=>d<=75;
when 21=>d<=64; when 22=>d<=53; when 23=>d<=43;
when 24=>d<=34; when 25=>d<=26; when 26=>d<=19;
when 27=>d<=13; when 28=>d<=8; when 29=>d<=4;
when 30=>d<=1; when 31=>d<=0; when 32=>d<=0;
when 33=>d<=1; when 34=>d<=4; when 35=>d<=8;
when 36=>d<=13; when 37=>d<=19; when 38=>d<=26;
when 39=>d<=34; when 40=>d<=43; when 41=>d<=53;
when 42=>d<=64; when 43=>d<=75; when 44=>d<=87;
when 45=>d<=99; when 46=>d<=112;when 47=>d<=124;
when 48=>d<=137;when 49=>d<=150;when 50=>d<=162;
when 51=>d<=174;when 52=>d<=186;when 53=>d<=197;
when 54=>d<=207;when 55=>d<=217;when 56=>d<=225;
when 57=>d<=233;when 58=>d<=239;when 59=>d<=245;
when 60=>d<=249;when 61=>d<=252;when 62=>d<=254;
when 63=>d<=255;when others =>null;
end case;
end if;
end process;
end sin_arc;
如图所示每当一个时钟的上升沿到来时都会将地址加 1 读取 rom 中的数据当地址加法
器计数到达 63 时候讲计数器的各位置零开始下一个周期的操作。
当时间到达 4.71us 时候开始下一个周期的取值运算操作。