咳咳,我又回来了。好像这段时间在软工上并没有做出什么成果可以写出博客出来分享的,每天就是改改几个BUG,又发现几个BUG,又去改改。
既然这样,这次就来写写其他学科完成的一些作业吧。首先先来篇EDA的,这个学科挺有意思的,也挺好玩的。
课程简介
首先,先简单说下这个学科是做什么的。通俗一点讲的话,这门课就是用软件来实现硬件设计。
采用的软件: Quartus II(PLD开发软件,注:PLD指可编程逻辑器件
采用的语言: VHDL(硬件描述语言
实验仪PLD型号:EP4CE10E22C8
实验题目:电子琴实验
实验原理
组成乐曲的每个音符的频率值以及持续时间是乐曲能连续演奏所需的基本数据。本实验的关键是如何用分频的方法,产生每个音符的频率,通过蜂鸣器放音。不同的音域,音符的频率也不同,比如低音段,1、2、3、4、5、6、7(do、re、mi、fa、so、la、xi) 对应的频率分别为:262HZ、294HZ、330HZ、349HZ、392HZ、440HZ、494HZ。这些频率的获得可以利用分频器(即计数器)来实现,比如用12MHZ作为时钟输入,计数到45801时,即可产生一个262HZ的频率,发出“1”(do)的声音。
实验内容
1、以AN按键作为琴键,用7个按键,代表1~7的音,当按键按下时,即发出相应的音。
2、请参考一些简谱资料,设计能自动演奏形如“祝你生日快乐”或“欢乐颂”等乐曲。
小小感触
这门课真的很好玩,当你敲了半天的代码,然后把代码烧录到实验仪上时那种激动人心的紧张是特别有意思的。因为,特别期待到底能不能发出那些优美的音符。
怎么说,做这种涉及到硬件底层的,总会有那么一丝丝好奇感,那么一丝丝自豪感。原来音符的发声就是这样产生的啊,原来时钟计时就是这样设计的啊等等。以前接触的都是那些别人已经封装完毕,你只需要会调用就好,体会不到这种神奇感觉。比如大一,最开始接触的是C语言,天天接触到的就是在一个黑框中输入输出,或许那时你会觉得有点无聊。
然后是大二,接触到了数据库。哇,你的电脑居然可以访问我电脑的数据; 快看,我写了个UDP广播,你快运行这个程序试试,看能不能收到我电脑发出的信息等等。这时,相比于大一的黑框,你会开始觉得代码好神奇,原来通信就是通过这样写代码实现的,你是不是也能写出个这样的出来,那简直就太屌了。
接下去就是大三,接触了java,android,软工实践。这时的你已经开始能做出一些简单的网页,简单的手机apk软件了。当然,老样子,这时候你还是会觉得自己简直碉堡了,怎么能不去炫耀炫耀呢。于是找到以前的老同学的讨论组,把apk往里一放,把网页url往里一发,然后满怀着骄傲的心情,用着不屑的口气敲打键盘:“看,这是哥哥自己写的网页(软件)!是自己写的哦!!”。然后想象着老朋友会一脸的崇拜,“哇,好厉害!”;“你自己写的?666” 然而你却忘记了你只会最简单最粗糙的技术,老同学早已是现代各种高特效网页(软件)里摸爬滚打起来的老司机了,哪里会看得上你第一次写出来的那种小东西?
于是乎,在你沉浸在自己的幻想中时,老同学冷冷的来了句:“卧槽!有毒,别点!!”;“某某某,你又乱逛什么网页了,QQ又重毒了? ; “号被盗了?某某某,你刚用QQ向我借了100块,记得还啊。
哎,人生难得一知己啊,你这时会吐槽道,哥哥怎么会有你们这帮损友!吐槽完后还是得去接着敲你的软工去。日子一天天过,这时你又开始接触新的一门实践了,EDA设计。刚开始时你还是忘不了吐槽,这学期的实践课怎么这么多。。。
然而,当你慢慢的接触到EDA实践中去时,你突然又发现了这门课好像很有意思。当做完自己设计的实验时,你突然感到无比骄傲,我居然设计出了电子琴了,居然可以演奏乐曲!hhh,赶紧去向老同学炫耀去!哦不!那群渣渣怎么能懂我的艺术。嗯~哦,有了,写博客去,到博客上炫耀炫耀hhhh!
然而,你却还是犯了老毛病,忘记了自己第一次设计出的东西能上得了台面吗?何况像这种大学里的课程跟着指导书设计的实验,网上早已经成大白菜,一抓一大把了,哪还有人有兴趣去欣赏你的炫耀去!哎,注定又是一堆炮轰。
然而,即便如此,你仍旧不觉得自己的爱嘚瑟的老毛病是个毛病,你仍旧沉浸于向老同学炫耀中,因为你知道,老同学其实是在鼓励你,肯定你,当然,你怎么可能只会做出这种小东西呢~这只是饭前甜品,你这样为自己安慰道。
VHDL代码
好像写着写着,不知道歪到哪里去了,本来就只是准备写写这个实验的,哎,罢了,反正看着好像也挺有趣,等经历再多点,写成小故事去~hhhh。
好了,还是赶紧完成这篇博客,最后就把代码贴上来吧。因为没做仿真,直接在实验仪上观察的结果,再加上电子琴实验实在没办法通过拍照等方式把结果展现出来,所以这里只能贴代码了。下周就要考EDA了,不知道还有没有时间做个交通灯,做出来的话就可以展示成果啦啦啦~~
本实验采用分模块设计,首先是一个按键检测模块,用来检测要发哪个音符或者是自动演奏
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY scanKey IS
PORT(AN: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
KEY: OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
EN1: OUT STD_LOGIC;
EN2: OUT STD_LOGIC);
END scanKey;
ARCHITECTURE one OF scanKey IS
BEGIN
PROCESS(AN)
BEGIN
--初始化使能,默认不选中任何一种模块工作
--EN1选中按键模块
--EN2选中自动播放模块
EN1<='0';
EN2<='0';
CASE AN IS --分别绑定八个按键
WHEN "00000001" => KEY<="001";EN1<='1';
WHEN "00000010" => KEY<="010";EN1<='1';
WHEN "00000100" => KEY<="011";EN1<='1';
WHEN "00001000" => KEY<="100";EN1<='1';
WHEN "00010000" => KEY<="101";EN1<='1';
WHEN "00100000" => KEY<="110";EN1<='1';
WHEN "01000000" => KEY<="111";EN1<='1';
WHEN "10000000" => EN2<='1';
WHEN OTHERS => EN1 <='0';EN2<='0';
END CASE;
END PROCESS;
END;
然后是一个分频输出模块,用来发出声音的
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_unsigned.ALL;
ENTITY count IS
PORT(CLK1:IN STD_LOGIC;
EN:IN STD_LOGIC;
KEY:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
OCLK:OUT STD_LOGIC);
END count;
ARCHITECTURE one OF count IS
SIGNAL CNT: STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
PROCESS(KEY)
BEGIN
CASE KEY IS
WHEN "001" => CNT<="1011001011101001";--262HZ do
WHEN "010" => CNT<="1001111101110000";--294HZ re
WHEN "011" => CNT<="1000111000001011";--330HZ mi
WHEN "100" => CNT<="1000011001010000";--349HZ fa
WHEN "101" => CNT<="0111011110010100";--392HZ so
WHEN "110" => CNT<="0110101010001001";--440HZ la
WHEN "111" => CNT<="0101111011100011";--494HZ xi
WHEN "000" => CNT<="0000000000000000"; --不发声
END CASE;
END PROCESS;
PROCESS(CLK1)
VARIABLE CQ : STD_LOGIC_VECTOR(15 DOWNTO 0) := "0000000000000000";
BEGIN
IF (CLK1'EVENT AND CLK1='1') THEN
IF EN='1' THEN
IF CQ<('0'&CNT(15 DOWNTO 1)) THEN
CQ:= CQ + 1;
OCLK <= '1';
ELSIF CQ<CNT THEN
CQ:=CQ+1;
OCLK <='0';
ELSE
CQ:=(OTHERS => '0');
OCLK<='1';
END IF;
ELSE
CQ:=(OTHERS => '0');
OCLK<='1';
END IF;
END IF;
END PROCESS;
END;
最后是一个顶层文件,用来协调各模块分工协作的。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY song IS
PORT(CLK1: IN STD_LOGIC;
CLK5:IN STD_LOGIC;
AN: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
F:OUT STD_LOGIC);
END song;
ARCHITECTURE one OF song IS
--元件例化
--分频输出模块
COMPONENT count
PORT(CLK1:IN STD_LOGIC;
KEY:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
EN:IN STD_LOGIC;
OCLK:OUT STD_LOGIC);
END COMPONENT;
--按键检测模块
COMPONENT scanKey
PORT(AN: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
KEY: OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
EN1: OUT STD_LOGIC;
EN2: OUT STD_LOGIC);
END COMPONENT;
SIGNAL key1:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL en1:STD_LOGIC;
SIGNAL f1,f2:STD_LOGIC;
BEGIN
u0:scanKey PORT MAP(AN,key1,en1,en2);
u1:count PORT MAP(CLK1,key1,en1,f1);
END;
注:实验内容2代码暂时没提供,以上代码只能实现实验1的功能,并且亲测可行。但由于课堂时间有限,还未来得及验证内容2的代码是否正确,所以暂时没提供,等下周上课再进行测试。