多功能波形发生器VHDL程序
--文件名:mine4.vhd。
--功能:实现4种常见波形正弦、三角、锯齿、方波(A、B)的频率、幅度可控输出(方波
--A的占空比也是可控的),可以存储任意波形特征数据并能重现该波形,还可完成
--各种波形的线形叠加输出。
--说明: SSS(前三位)和SW信号控制4种常见波形种哪种波形输出。4种波形的频率、
--幅度(基准幅度A)的调节均是通过up、down、set按键和4个BCD码置入器以及一
--个置入档位控制信号(ss)完成的(AMP的调节范围是0~5V,调节量阶为1/51V)。
--其中方波的幅度还可通过u0、d0调节输出数据的归一化幅值(AMP0)进行进一步
--细调(调节量阶为1/(51*255)V)。方波A的占空比通过zu、zp按键调节(调节
--量阶1/64*T)。系统采用内部存储器——RAM实现任意输入波形的存储,程序只支
--持键盘式波形特征参数置入存储,posting 为进入任意波置入(set)、清除(clr)状态
--控制信号,SSS控制存储波形的输出。P180为预留端口,
--最后修改日期:2004.3.26。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity mine4 is
port(clk : in std_logic; --时钟信号输入
set, clr, up, down, zu, zd : in std_logic; --各个波形特征的调节触发信号
posting : in std_logic; --任意波键盘置入信号
u0,d0,sw : in std_logic; --方波A、B的切换sw,和方波B的幅度调节按键
ss : in std_logic_vector( 3 downto 0 ); --档位选择信号
sss : in std_logic_vector( 4 downto 0 ); --波形选择信号
Data3, Data2, Data1,Data0 : in std_logic_vector(3 downto 0); --BCD码输入
p180 : out std_logic; --预留接口
lcd : out std_logic_vector(7 downto 0); --显示输出
shift : out std_logic_vector(3 downto 0); --位码输出
dd, a : out std_logic_vector( 7 downto 0)); --波形、幅度数据输出
end mine4;
architecture behav of mine4 is
subtype word is std_logic_vector( 7 downto 0 );
type unit is array(63 downto 0) of word;
signal ram : unit;
signal qqq : integer range 0 to 250000000;
signal qq : integer range 0 to 78125000;
signal tmp : integer range 0 to 9999;
signal coun : integer range 0 to 78125000;
signal coun0 : integer range 0 to 250000000;
signal b : integer range 0 to 78125000;
signal c : integer range 0 to 500000000;
signal z, con : integer range 0 to 63;
signal f : std_logic_vector( 7 downto 0 );
signal amp, amp0, d : std_logic_vector(7 downto 0);
signal bcd0,bcd1,bcd2,bcd3 : integer range 0 to 9;
signal bcd01,bcd11,bcd21,bcd31 : integer range 0 to 9;
signal bcd00,bcd10,bcd20,bcd30 : integer range 0 to 9;
signal y : integer range 0 to 9;
signal addr : integer range 0 to 63;
begin
qq<=781250 when ss="1000" else
7812500 when ss="0100" else
78125000 when ss="0010" else
78125;
--qq信号对应SW=0时的档位选择信号SS,实现方波A和其他三种波形的频率预置
qqq<= 500000 when ss="1000" else
5000000 when ss="0100" else
50000000 when ss="0010" else
50000;
--qqq信号对应SW=1时的档位选择信号SS,实现方波B的频率预置
process(clk)
--此进程分别描述了各种波形的频率、幅度(方波A的占空比)调节以及各种波形的任意线
--形叠加等。
variable count4 : integer range 0 to 6250000;
variable count : integer range 0 to 78125000;
variable count3 : integer range 0 to 250000000;
variable count1 : integer range 0 to 12500000;
variable count0 : integer range 0 to 3249999;
variable ddd : std_logic_vector(9 downto 0);
variable dd0,dd1,dd2,dd3,dd4 : integer range 0 to 255;
variable adr : integer range 0 to 63;
begin
if rising_edge(clk) then
if posting='1' then
if count4=6249999 then count4:=0;
adr:=conv_integer(Data3)*10+conv_integer(Data2);--存储单位地址
if adr<64 then
if set='1' then ram(adr)<=conv_std_logic_vector((conv_integer(Data1)*10
+conv_integer(Data0))*2,8); --对置入的任意波形数据进行储存
elsif clr='1' then adr:=0; --存储器所有单元清零
for i in 0 to 63 loop
ram(i)<=(others=>'0');
end loop;
end if;
end if;
else count4:=count4+1;
end if;
else
if set='1' then coun<=0; b<=0; coun0<=0;c<=0;z<=31;amp0<="01111111"; addr<=0;
tmp<=conv_integer(Data3)*1000+conv_integer(Data2)*100
+conv_integer(Data1)*10+conv_integer(Data0); --频率数据
amp<="01111111"; --幅值
else
if tmp>0 then
if sw='0' then
if coun<qq then coun<=coun+tmp; b<=b+1; --频率到采样点间隔脉冲数转换
else
if count=b then count:=1;
if f=63 then f<="00000000";
else f<=f+1;
end if;
if sss="00010" then --方波A
if con<=z then dd<=amp0; con<=con+1;
elsif con=63 then con<=0; dd<="00000000";
else con<=con+1; dd<="00000000";
end if;
elsif sss="10000" then dd<=d; --正弦波
elsif sss="00100" then dd<=f(5 downto 0)&"00"; --锯齿波
elsif sss="01000" then --三角波
if f>31 then dd<=("111111"-f(5 downto 0))&"00";
else dd<=f(5 downto 0)&"00";
end if;
elsif sss="00001" then --任意波
if addr<63 then dd<=ram(addr); addr<=addr+1;
elsif addr=63 then dd<=ram(63); addr<=0;
end if;
else --完成5种波形的线形叠加
if sss(1)='1' then
if con<=z then con<=con+1;
dd0:=conv_integer(amp0); --方波波形数据dd0
else con<=con+1; dd0:=0;
end if;
end if;
if sss(4)='1' then dd1:=conv_integer(d); --正弦波波形数据dd1
end if;
if sss(2)='1' then dd2:=conv_integer(f(5 downto 0)&"00");
--锯齿波波形数据dd2
end if;
if sss(3)='1' then
if f>31 then dd3:=conv_integer(("111111"-f(5 downto 0))&"00");
else dd3:=conv_integer(f(5 downto 0)&"00"); --三角波波形数据dd3
end if;
end if;
if sss(0)='1' then
if addr<63 then dd4:=conv_integer(ram(addr)); addr<=addr+1;
elsif addr=63 then dd4:=conv_integer(ram(63)); addr<=0;
end if; --任意波波形数据dd4
end if;
ddd:=conv_std_logic_vector((dd0+dd1+dd2+dd3+dd4),10);
--波形线形叠加输出
dd<=ddd(9 downto 2);
end if;
else count:=count+1;
end if;
end if;
else
if coun0<qqq then coun0<=coun0+tmp; c<=c+1;
else
if count3<=c/2 then count3:=count3+1; dd<=amp0;
elsif count3=c then count3:=1;dd<="00000000";
else count3:=count3+1; dd<="00000000";
end if;
end if;
end if;
end if;
if count1=12499999 then count1:=0; --调方波A的占空比
if zu='1' then
if z<63 then z<=z+1;
else z<=63;
end if;
elsif zd='1' then
if z>0 then z<=z-1;
else z<=0;
end if;
end if;
else count1:=count1+1;
end if;
if count0=3249999 then count0:=0;
--up、down对4种波形幅度调节,u0、d0进一步对方波进行幅度调节
if u0='1' then
if amp0<"11111111" then amp0<=amp0+1;
else amp0<="11111111";
end if;
elsif d0='1' then
if amp0>"00000000" then amp0<=amp0-1;
else amp0<="00000000";
end if;
elsif up='1' then
if amp<"11111111" then amp<=amp+1;
else amp<="11111111";
end if;
elsif down='1' then
if amp>"00000000" then amp<=amp-1;
else amp<="00000000";
end if;
end if;
else count0:=count0+1;
end if;
end if;
end if;
end if;
end process;
a<=amp; --将幅值输出。
cov_a:process(clk,amp,amp0)
--主要实现各波形幅度值到BCD码的转化,由于方波和其他三种波形的幅度调节方式、精
--度不同,因此对幅度的处理方式分两种:“sss="00010" or sw='1'”是判断输出波形是否为
--方波(A或B),bcd00,bcd10,bcd20,bcd30是本进程的输出。
variable count : integer range 0 to 50004225;
variable counter : integer range 0 to 500055;
variable count1,count0 : integer range 0 to 4999999;
begin
if rising_edge(clk) then
if sss="00010" or sw='1' then count0:=0; --方波
if count1=4999999 then count1:=0; bcd0<=0; bcd1<=0; bcd2<=0; bcd3<=0;
count:=(conv_integer(amp))*(conv_integer(amp0))*769; --幅值运算
elsif count1=4999900 then count1:=count1+1;
bcd00<=bcd0; bcd10<=bcd1; bcd20<=bcd2; bcd30<=bcd3; --数据输出
else count1:=count1+1; --二进制码到BCD码的数据转换
if count>9999999 then count:=count-10000000; bcd0<=bcd0+1;
elsif count>999999 then count:=count-1000000; bcd1<=bcd1+1;
elsif count>99999 then count:=count-100000; bcd2<=bcd2+1;
elsif count>9999 then count:=count-10000; bcd3<=bcd3+1;
else null;
end if;
end if;
else count1:=0; --正弦波、三角波、锯齿波
if count0=4999999 then counter:=conv_integer(amp)*1961;
count0:=0; bcd01<=0; bcd11<=0; bcd21<=0; bcd31<=0;
elsif count0=4999000 then bcd00<=bcd01; bcd10<=bcd11; bcd20<=bcd21;
bcd30<=bcd31; count0:=count0+1;
else count0:=count0+1;
if counter>99999 then counter:=counter-100000; bcd01<=bcd01+1;
elsif counter>9999 then counter:=counter-10000; bcd11<=bcd11+1;
elsif counter>999 then counter:=counter-1000; bcd21<=bcd21+1;
elsif counter>99 then counter:=counter-100; bcd31<=bcd31+1;
else null;
end if;
end if;
end if;
end if;
end process;
process(clk) --输出波形幅度(峰-峰值)数据译码动态显示
variable count : integer range 0 to 499999;
begin
if rising_edge(clk) then
if count<=124999 then y<=bcd00; count:=count+1; shift<="0111"; lcd(0)<='0';
elsif count<=249999 then y<=bcd10; count:=count+1; shift<="1011";lcd(0)<='1';
elsif count<=374999 then y<=bcd20; count:=count+1; shift<="1101";lcd(0)<='1';
elsif count<499999 then y<=bcd30; count:=count+1; shift<="1110";lcd(0)<='1';
elsif count=499999 then y<=bcd30; count:=0; shift<="1110";lcd(0)<='1';
end if;
end if;
case y is --7段码译码
when 0 => lcd(7 downto 1)<="0000001";
when 1 => lcd(7 downto 1)<="1001111";
when 2 => lcd(7 downto 1)<="0010010";
when 3 => lcd(7 downto 1)<="0000110";
when 4 => lcd(7 downto 1)<="1001100";
when 5 => lcd(7 downto 1)<="0100100";
when 6 => lcd(7 downto 1)<="0100000";
when 7 => lcd(7 downto 1)<="0001111";
when 8 => lcd(7 downto 1)<="0000000";
when 9 => lcd(7 downto 1)<="0000100";
when others => lcd(7 downto 1)<="0000001";
end case;
end process;
ym:process(clk) --正弦波在一个周期内时域上的64个采样点的波形数据
begin
if rising_edge(clk) then
case f is
when "00000000"=> d<="11111111" ; when "00000001"=> d<="11111110" ;
when "00000010"=> d<="11111100" ;when "00000011"=> d<="11111001" ;
when "00000100"=> d<="11110101" ; when "00000101"=> d<="11101111" ;
when "00000110"=> d<="11101001" ;when "00000111"=> d<="11100001" ;
when "00001000"=> d<="11011001" ; when "00001001"=> d<="11001111" ;
when "00001010"=> d<="11000101" ;when "00001011"=> d<="10111010" ;
when "00001100"=> d<="10101110" ; when "00001101"=> d<="10100010" ;
when "00001110"=> d<="10010110" ;when "00001111"=> d<="10001001" ;
when "00010000"=> d<="01111100" ; when "00010001"=> d<="01110000" ;
when "00010010"=> d<="01100011" ;when "00010011"=> d<="01010111" ;
when "00010100"=> d<="01001011" ; when "00010101"=> d<="01000000" ;
when "00010110"=> d<="00110101" ;when "00010111"=> d<="00101011" ;
when "00011000"=> d<="00100010" ; when "00011001"=> d<="00011010" ;
when "00011010"=> d<="00010011" ;when "00011011"=> d<="00001101" ;
when "00011100"=> d<="00001000" ; when "00011101"=> d<="00000100" ;
when "00011110"=> d<="00000001" ;when "00011111"=> d<="00000000" ;
when "00100000"=> d<="00000000" ; when "00100001"=> d<="00000001" ;
when "00100010"=> d<="00000100" ;when "00100011"=> d<="00001000" ;
when "00100100"=> d<="00001101" ; when "00100101"=> d<="00010011" ;
when "00100110"=> d<="00011010" ;when "00100111"=> d<="00100010" ;
when "00101000"=> d<="00101011" ; when "00101001"=> d<="00110101" ;
when "00101010"=> d<="01000000" ;when "00101011"=> d<="01001011" ;
when "00101100"=> d<="01010111" ; when "00101101"=> d<="01100011" ;
when "00101110"=> d<="01110000" ;when "00101111"=> d<="01111100" ;
when "00110000"=> d<="10001001" ; when "00110001"=> d<="10010110" ;
when "00110010"=> d<="10100010" ;when "00110011"=> d<="10101110" ;
when "00110100"=> d<="10111010" ; when "00110101"=> d<="11000101" ;
when "00110110"=> d<="11001111" ;when "00110111"=> d<="11011001" ;
when "00111000"=> d<="11100001" ; when "00111001"=> d<="11101001" ;
when "00111010"=> d<="11101111" ;when "00111011"=> d<="11110101" ;
when "00111100"=> d<="11111001" ; when "00111101"=> d<="11111100" ;
when "00111110"=> d<="11111110" ;when "00111111"=> d<="11111111" ;
when others=> null;
end case;
end if;
end process;
p180<='1';
end behav;
步进电机定位控制系统VHDL程序
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity step_motor is
port (reset:in STD_LOGIC; --系统复位信号
dir: in STD_LOGIC; --方向控制信号
clk: in STD_LOGIC; --系统时钟信号
ini: in STD_LOGIC; --初始化使能信号
manner: in STD_LOGIC_VECTOR (1 downto 0); --激磁方式的选择开关
angle: in INTEGER range 255 downto 0; --步进角的倍数设定输入
baBA: out STD_LOGIC_VECTOR (3 downto 0)); --步进电机状态输出
end step_motor;
architecture stepmotor_arch of step_motor is
signal count: INTEGER range 0 to 7; --计数器
signal cntInc: INTEGER range -2 to 2; --设定累加器所需的累(加/减)计数值
signal cc : integer range 0 to 3;
signal cntIni: INTEGER range -1 to 0; --设定累加器所需的计数初值
signal angleDnCount: INTEGER range 255 downto 0; --计算已经转过的步进角
signal angleDnCntDec: INTEGER range 2 downto 1;
begin
process(dir, manner, angle)--, ini)
begin
--if ini='1' then
cc<=conv_integer(manner);
if dir='0' then
case cc is
when 1 => -- 1-相激励
--count<=0;
cntIni<=0;
cntInc<=2;
angleDnCntDec<=2;--"10";
when 2 => -- 2-相激励
--count<=7;
cntIni<=-1;
cntInc<=2;
angleDnCntDec<=2;--"10";
when 3 => -- 1-2相激励
--count<=0;
cntIni<=0;
cntInc<=1;
angleDnCntDec<=1;--"01";
when 0 => --manner="00" autodetect
if (angle rem 2) =1 then -- 2-相激励
--count<=7;
cntIni<=-1;
cntInc<=2;
angleDnCntDec<=2;--"10";
else -- 1-相激励
--count<=0;
cntIni<=0;
cntInc<=2;
angleDnCntDec<=2;--"10";
end if; --angle
end case; --manner
else -- if dir='1'
case cc is
when 1 => -- 1-相激励
--count<=0;
cntIni<=0;
cntInc<=-2;
angleDnCntDec<=2;--"10";
when 2 => -- 2-相激励
--count<=7;
cntIni<=-1;
cntInc<=-2;
angleDnCntDec<=2;--"10";
when 3 => -- 1-2相激励
--count<=0;
cntIni<=0;
cntInc<=-1;
angleDnCntDec<=1;--"01";
when 0 => --manner="00" autodetect
if (angle rem 2) = 1 then -- 2-相激励
cntIni<=-1;
cntInc<=-2;
angleDnCntDec<=2;--"10";
else -- 1-相激励
cntIni<=0;
cntInc<=-2;
angleDnCntDec<=2;--"10";
end if; --angle
end case; --manner
end if; -- else dir=0
--end if; -- ini
end process;
counting_reset: process(reset,ini, angle, clk)
begin
if reset='1' then
count<=0;
angleDnCount<=0;
elsif clk'event and clk='1' then
if ini='0' then
count<=0+cntIni;
angleDnCount<=angle;
else
count <= count+cntInc;
if angleDnCount > angleDnCntDec then
angleDnCount <= angleDnCount-angleDnCntDec;
else
angleDnCount <= 0;
end if;
end if;
end if;
end process;
baBA <="0000" when angleDnCount=0 else
"0001" when count=0 else
"0011" when count=1 else
"0010" when count=2 else
"0110" when count=3 else
"0100" when count=4 else
"1100" when count=5 else
"1000" when count=6 else
"1001";-- when count>=7;
end stepmotor_arch;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity step_motor is
port (reset:in STD_LOGIC; --系统复位信号
dir: in STD_LOGIC; --方向控制信号
clk: in STD_LOGIC; --系统时钟信号
ini: in STD_LOGIC; --初始化使能信号
manner: in STD_LOGIC_VECTOR (1 downto 0); --激磁方式的选择开关
angle: in INTEGER range 255 downto 0; --步进角的倍数设定输入
baBA: out STD_LOGIC_VECTOR (3 downto 0)); --步进电机状态输出
end step_motor;
architecture stepmotor_arch of step_motor is
signal count: INTEGER range 0 to 7; --计数器
signal cntInc: INTEGER range -2 to 2; --设定累加器所需的累(加/减)计数值
signal cc : integer range 0 to 3;
signal cntIni: INTEGER range -1 to 0; --设定累加器所需的计数初值
signal angleDnCount: INTEGER range 255 downto 0; --计算已经转过的步进角
signal angleDnCntDec: INTEGER range 2 downto 1;
begin
process(dir, manner, angle)--, ini)
begin
--if ini='1' then
cc<=conv_integer(manner);
if dir='0' then
case cc is
when 1 => -- 1-相激励
--count<=0;
cntIni<=0;
cntInc<=2;
angleDnCntDec<=2;--"10";
when 2 => -- 2-相激励
--count<=7;
cntIni<=-1;
cntInc<=2;
angleDnCntDec<=2;--"10";
when 3 => -- 1-2相激励
--count<=0;
cntIni<=0;
cntInc<=1;
angleDnCntDec<=1;--"01";
when 0 => --manner="00" autodetect
if (angle rem 2) =1 then -- 2-相激励
--count<=7;
cntIni<=-1;
cntInc<=2;
angleDnCntDec<=2;--"10";
else -- 1-相激励
--count<=0;
cntIni<=0;
cntInc<=2;
angleDnCntDec<=2;--"10";
end if; --angle
end case; --manner
else -- if dir='1'
case cc is
when 1 => -- 1-相激励
--count<=0;
cntIni<=0;
cntInc<=-2;
angleDnCntDec<=2;--"10";
when 2 => -- 2-相激励
--count<=7;
cntIni<=-1;
cntInc<=-2;
angleDnCntDec<=2;--"10";
when 3 => -- 1-2相激励
--count<=0;
cntIni<=0;
cntInc<=-1;
angleDnCntDec<=1;--"01";
when 0 => --manner="00" autodetect
if (angle rem 2) = 1 then -- 2-相激励
cntIni<=-1;
cntInc<=-2;
angleDnCntDec<=2;--"10";
else -- 1-相激励
cntIni<=0;
cntInc<=-2;
angleDnCntDec<=2;--"10";
end if; --angle
end case; --manner
end if; -- else dir=0
--end if; -- ini
end process;
counting_reset: process(reset,ini, angle, clk)
begin
if reset='1' then
count<=0;
angleDnCount<=0;
elsif clk'event and clk='1' then
if ini='0' then
count<=0+cntIni;
angleDnCount<=angle;
else
count <= count+cntInc;
if angleDnCount > angleDnCntDec then
angleDnCount <= angleDnCount-angleDnCntDec;
else
angleDnCount <= 0;
end if;
end if;
end if;
end process;
baBA <="0000" when angleDnCount=0 else
"0001" when count=0 else
"0011" when count=1 else
"0010" when count=2 else
"0110" when count=3 else
"0100" when count=4 else
"1100" when count=5 else
"1000" when count=6 else
"1001";-- when count>=7;
end stepmotor_arch;
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 | |
【FRDM-MCXN947评测】核间通信MUTEX被打赏50分 |