前言
DDS(Direct Digital Synthesis)载波发生器是一种利用数字合成技术生成波形信号的设备。它可以产生非常精确、稳定的频率信号,广泛应用于信号处理、通信系统、测试和测量等领域。本章节利用IP核rom,设计一能够进行波形切换,频率变化,振幅变化的波形发生器。
正文
一、DDS载波发生器
1.项目需求
设计一个能够进行波形切换(正弦波,方波,三角波,锯齿波),频率变化,振幅变化的波形发生器,通过独立按键对这些功能进行控制,利用IP核进行设计。
2.技术介绍
假设已经将正弦波数据(256个)存储到rom中,假设利用驱动时钟控制rom地址一个时钟周期变换一次,那么产生的正弦波频率为:1/256*20(ns) =195.3125khz。
如果不能改变驱动时钟频率,如果将产生的正弦波频率增大,控地址在每一次变化加2,只能怪读取128个数据,产生的正弦波频率为:390.625khz,在不改变驱动时钟频率,同时也不能丢失正弦波数据,控制地址两个驱动时钟周期变化一次,那么产生的正弦波频率为:(1/256*20(ns))/ 2 = 97.656khz;
根据这样的逻辑,产生一个目标频率小于1hz正弦波,假设地址变化一次需要经过256个驱动时钟周期,可以产生一个8位的循环计数器,当其计数到255时rom地址变化一次,就可以将地址和计数器拼接起来形成一个新的计数器,新的计数器的位宽为16位的,高8位表示rom地址,可以得到一个频率为:(1/256*20(ns))/ 2^8 = 762.94hz正弦波。
产生一个24位的计数器,高8位表示rom地址,那么产生的正弦波频率为:(1/256*20(ns))/ 2^16 =2.98hz
产生一个26位的计数器,高8位表示rom地址,那么产生的正弦波频率为:(1/256*20(ns))/ 2^18=0.745hz.
产生一个32位的计数器,高8位表示rom地址,那么产生的正弦波频率为:(1/256*20(ns))/ 2^24=0.0116hz
从这里可以看出,用到的计数器位数越多,产生的信号频率越小,频率越小,信号的精确度越高,这里引进一个概念:频率控制字。频率控制字的精度受限于其位数,因此更高位数的控制字可以提供更高的频率分辨率。
频率控制字:(FCLK系统时钟50Mhz,频率控制字为32位N=32)
假设产生一个10khz的正弦波,频率控制字为:(10khz/50Mhz)*2^32=858993
1.波形切换
需要实现四种波形的切换,默认显示的波形为正弦波,切换波形的顺序为:正弦—方波—三角波—锯齿波—正弦,每一个波形数据提取的波形数据宽度为8位,深度为256,通过第三方软件,将四种波形的数据提取出来,合并在一起,形成一个深度为1024,宽度为8的Mif文件。
第一个正弦波时,地址在0到255变化
第二个方波时,地址在256到511变化
第三个三角波时,地址在512到767变化
第四个锯齿波时,地址在768到1023变化
利用有限状态机理论进行控制,将每一种波形显示作为一个状态,四个状态的跳转条件为切换按键进行一次操作,状态在跳转的同时,需要将每一个状态开始的初始地址数值给到地址变量。
2.频率变化
地址变化控制频率变化的变量addr给到rom_addr,让其rom_addr = addr + (256,512,678) 在控制频率变化变量模块里的频率控制字需要作为变量产生,在没有对波形频率进行控制变化时,默认每一个波形频率为:50khz,每对控制波形频率按键操作一次,频率增加50khz,控制频率最大变化到1mhz,那么频率控制字就有20种变化,通过控制频率按键的操作次数控制产生频率控制字。
3.振幅变化
改变振幅改变的是波形数据的大小,不管哪一种波形,其数据大小范围:0到255,在进行波形振幅控制变化时,最大将波形数据范围修改为0到510,每对波形振幅按键进行一次操作时,波形的数据增大32。
制作包含各类波数据的mif文件,调用IP核rom(具体调用方法参考IP核ROM调用)
-- Copyright (C) 1991-2013 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Quartus II generated Memory Initialization File (.mif)
WIDTH=8;
DEPTH=1024;
ADDRESS_RADIX=UNS;
DATA_RADIX=UNS;
CONTENT BEGIN
0 : 128;
1 : 131;
2 : 134;
3 : 137;
4 : 140;
5 : 143;
6 : 146;
7 : 149;
8 : 152;
9 : 155;
10 : 158;
11 : 162;
12 : 165;
13 : 167;
14 : 170;
15 : 173;
16 : 176;
17 : 179;
18 : 182;
19 : 185;
20 : 188;
21 : 190;
22 : 193;
23 : 196;
24 : 198;
25 : 201;
26 : 203;
27 : 206;
28 : 208;
29 : 211;
30 : 213;
31 : 215;
32 : 218;
33 : 220;
34 : 222;
35 : 224;
36 : 226;
37 : 228;
38 : 230;
39 : 232;
40 : 234;
41 : 235;
42 : 237;
43 : 238;
44 : 240;
45 : 241;
46 : 243;
47 : 244;
48 : 245;
49 : 246;
50 : 248;
51 : 249;
[52..53] : 250;
54 : 251;
55 : 252;
[56..57] : 253;
[58..60] : 254;
[61..67] : 255;
[68..70] : 254;
[71..72] : 253;
73 : 252;
74 : 251;
[75..76] : 250;
77 : 249;
78 : 248;
79 : 246;
80 : 245;
81 : 244;
82 : 243;
83 : 241;
84 : 240;
85 : 238;
86 : 237;
87 : 235;
88 : 234;
89 : 232;
90 : 230;
91 : 228;
92 : 226;
93 : 224;
94 : 222;
95 : 220;
96 : 218;
97 : 215;
98 : 213;
99 : 211;
100 : 208;
101 : 206;
102 : 203;
103 : 201;
104 : 198;
105 : 196;
106 : 193;
107 : 190;
108 : 188;
109 : 185;
110 : 182;
111 : 179;
112 : 176;
113 : 173;
114 : 170;
115 : 167;
116 : 165;
117 : 162;
118 : 158;
119 : 155;
120 : 152;
121 : 149;
122 : 146;
123 : 143;
124 : 140;
125 : 137;
126 : 134;
127 : 131;
128 : 127;
129 : 124;
130 : 121;
131 : 118;
132 : 115;
133 : 112;
134 : 109;
135 : 106;
136 : 103;
137 : 100;
138 : 97;
139 : 93;
140 : 90;
141 : 88;
142 : 85;
143 : 82;
144 : 79;
145 : 76;
146 : 73;
147 : 70;
148 : 67;
149 : 65;
150 : 62;
151 : 59;
152 : 57;
153 : 54;
154 : 52;
155 : 49;
156 : 47;
157 : 44;
158 : 42;
159 : 40;
160 : 37;
161 : 35;
162 : 33;
163 : 31;
164 : 29;
165 : 27;
166 : 25;
167 : 23;
168 : 21;
169 : 20;
170 : 18;
171 : 17;
172 : 15;
173 : 14;
174 : 12;
175 : 11;
176 : 10;
177 : 9;
178 : 7;
179 : 6;
[180..181] : 5;
182 : 4;
183 : 3;
[184..185] : 2;
[186..188] : 1;
[189..195] : 0;
[196..198] : 1;
[199..200] : 2;
201 : 3;
202 : 4;
[203..204] : 5;
205 : 6;
206 : 7;
207 : 9;
208 : 10;
209 : 11;
210 : 12;
211 : 14;
212 : 15;
213 : 17;
214 : 18;
215 : 20;
216 : 21;
217 : 23;
218 : 25;
219 : 27;
220 : 29;
221 : 31;
222 : 33;
223 : 35;
224 : 37;
225 : 40;
226 : 42;
227 : 44;
228 : 47;
229 : 49;
230 : 52;
231 : 54;
232 : 57;
233 : 59;
234 : 62;
235 : 65;
236 : 67;
237 : 70;
238 : 73;
239 : 76;
240 : 79;
241 : 82;
242 : 85;
243 : 88;
244 : 90;
245 : 93;
246 : 97;
247 : 100;
248 : 103;
249 : 106;
250 : 109;
251 : 112;
252 : 115;
253 : 118;
254 : 121;
255 : 124;
[256..383] : 0;
[384..511] : 255;
512 : 0;
513 : 2;
514 : 4;
515 : 6;
516 : 8;
517 : 10;
518 : 12;
519 : 14;
520 : 16;
521 : 18;
522 : 20;
523 : 22;
524 : 24;
525 : 26;
526 : 28;
527 : 30;
528 : 32;
529 : 34;
530 : 36;
531 : 38;
532 : 40;
533 : 42;
534 : 44;
535 : 46;
536 : 48;
537 : 50;
538 : 52;
539 : 54;
540 : 56;
541 : 58;
542 : 60;
543 : 62;
544 : 64;
545 : 66;
546 : 68;
547 : 70;
548 : 72;
549 : 74;
550 : 76;
551 : 78;
552 : 80;
553 : 82;
554 : 84;
555 : 86;
556 : 88;
557 : 90;
558 : 92;
559 : 94;
560 : 96;
561 : 98;
562 : 100;
563 : 102;
564 : 104;
565 : 106;
566 : 108;
567 : 110;
568 : 112;
569 : 114;
570 : 116;
571 : 118;
572 : 120;
573 : 122;
574 : 124;
575 : 126;
576 : 128;
577 : 129;
578 : 131;
579 : 133;
580 : 135;
581 : 137;
582 : 139;
583 : 141;
584 : 143;
585 : 145;
586 : 147;
587 : 149;
588 : 151;
589 : 153;
590 : 155;
591 : 157;
592 : 159;
593 : 161;
594 : 163;
595 : 165;
596 : 167;
597 : 169;
598 : 171;
599 : 173;
600 : 175;
601 : 177;
602 : 179;
603 : 181;
604 : 183;
605 : 185;
606 : 187;
607 : 189;
608 : 191;
609 : 193;
610 : 195;
611 : 197;
612 : 199;
613 : 201;
614 : 203;
615 : 205;
616 : 207;
617 : 209;
618 : 211;
619 : 213;
620 : 215;
621 : 217;
622 : 219;
623 : 221;
624 : 223;
625 : 225;
626 : 227;
627 : 229;
628 : 231;
629 : 233;
630 : 235;
631 : 237;
632 : 239;
633 : 241;
634 : 243;
635 : 245;
636 : 247;
637 : 249;
638 : 251;
639 : 253;
640 : 255;
641 : 253;
642 : 251;
643 : 249;
644 : 247;
645 : 245;
646 : 243;
647 : 241;
648 : 239;
649 : 237;
650 : 235;
651 : 233;
652 : 231;
653 : 229;
654 : 227;
655 : 225;
656 : 223;
657 : 221;
658 : 219;
659 : 217;
660 : 215;
661 : 213;
662 : 211;
663 : 209;
664 : 207;
665 : 205;
666 : 203;
667 : 201;
668 : 199;
669 : 197;
670 : 195;
671 : 193;
672 : 191;
673 : 189;
674 : 187;
675 : 185;
676 : 183;
677 : 181;
678 : 179;
679 : 177;
680 : 175;
681 : 173;
682 : 171;
683 : 169;
684 : 167;
685 : 165;
686 : 163;
687 : 161;
688 : 159;
689 : 157;
690 : 155;
691 : 153;
692 : 151;
693 : 149;
694 : 147;
695 : 145;
696 : 143;
697 : 141;
698 : 139;
699 : 137;
700 : 135;
701 : 133;
702 : 131;
703 : 129;
704 : 128;
705 : 126;
706 : 124;
707 : 122;
708 : 120;
709 : 118;
710 : 116;
711 : 114;
712 : 112;
713 : 110;
714 : 108;
715 : 106;
716 : 104;
717 : 102;
718 : 100;
719 : 98;
720 : 96;
721 : 94;
722 : 92;
723 : 90;
724 : 88;
725 : 86;
726 : 84;
727 : 82;
728 : 80;
729 : 78;
730 : 76;
731 : 74;
732 : 72;
733 : 70;
734 : 68;
735 : 66;
736 : 64;
737 : 62;
738 : 60;
739 : 58;
740 : 56;
741 : 54;
742 : 52;
743 : 50;
744 : 48;
745 : 46;
746 : 44;
747 : 42;
748 : 40;
749 : 38;
750 : 36;
751 : 34;
752 : 32;
753 : 30;
754 : 28;
755 : 26;
756 : 24;
757 : 22;
758 : 20;
759 : 18;
760 : 16;
761 : 14;
762 : 12;
763 : 10;
764 : 8;
765 : 6;
766 : 4;
767 : 2;
768 : 0;
769 : 1;
770 : 2;
771 : 3;
772 : 4;
773 : 5;
774 : 6;
775 : 7;
776 : 8;
777 : 9;
778 : 10;
779 : 11;
780 : 12;
781 : 13;
782 : 14;
783 : 15;
784 : 16;
785 : 17;
786 : 18;
787 : 19;
788 : 20;
789 : 21;
790 : 22;
791 : 23;
792 : 24;
793 : 25;
794 : 26;
795 : 27;
796 : 28;
797 : 29;
798 : 30;
799 : 31;
800 : 32;
801 : 33;
802 : 34;
803 : 35;
804 : 36;
805 : 37;
806 : 38;
807 : 39;
808 : 40;
809 : 41;
810 : 42;
811 : 43;
812 : 44;
813 : 45;
814 : 46;
815 : 47;
816 : 48;
817 : 49;
818 : 50;
819 : 51;
820 : 52;
821 : 53;
822 : 54;
823 : 55;
824 : 56;
825 : 57;
826 : 58;
827 : 59;
828 : 60;
829 : 61;
830 : 62;
831 : 63;
832 : 64;
833 : 65;
834 : 66;
835 : 67;
836 : 68;
837 : 69;
838 : 70;
839 : 71;
840 : 72;
841 : 73;
842 : 74;
843 : 75;
844 : 76;
845 : 77;
846 : 78;
847 : 79;
848 : 80;
849 : 81;
850 : 82;
851 : 83;
852 : 84;
853 : 85;
854 : 86;
855 : 87;
856 : 88;
857 : 89;
858 : 90;
859 : 91;
860 : 92;
861 : 93;
862 : 94;
863 : 95;
864 : 96;
865 : 97;
866 : 98;
867 : 99;
868 : 100;
869 : 101;
870 : 102;
871 : 103;
872 : 104;
873 : 105;
874 : 106;
875 : 107;
876 : 108;
877 : 109;
878 : 110;
879 : 111;
880 : 112;
881 : 113;
882 : 114;
883 : 115;
884 : 116;
885 : 117;
886 : 118;
887 : 119;
888 : 120;
889 : 121;
890 : 122;
891 : 123;
892 : 124;
893 : 125;
894 : 126;
895 : 127;
[896..897] : 128;
898 : 129;
899 : 130;
900 : 131;
901 : 132;
902 : 133;
903 : 134;
904 : 135;
905 : 136;
906 : 137;
907 : 138;
908 : 139;
909 : 140;
910 : 141;
911 : 142;
912 : 143;
913 : 144;
914 : 145;
915 : 146;
916 : 147;
917 : 148;
918 : 149;
919 : 150;
920 : 151;
921 : 152;
922 : 153;
923 : 154;
924 : 155;
925 : 156;
926 : 157;
927 : 158;
928 : 159;
929 : 160;
930 : 161;
931 : 162;
932 : 163;
933 : 164;
934 : 165;
935 : 166;
936 : 167;
937 : 168;
938 : 169;
939 : 170;
940 : 171;
941 : 172;
942 : 173;
943 : 174;
944 : 175;
945 : 176;
946 : 177;
947 : 178;
948 : 179;
949 : 180;
950 : 181;
951 : 182;
952 : 183;
953 : 184;
954 : 185;
955 : 186;
956 : 187;
957 : 188;
958 : 189;
959 : 190;
960 : 191;
961 : 192;
962 : 193;
963 : 194;
964 : 195;
965 : 196;
966 : 197;
967 : 198;
968 : 199;
969 : 200;
970 : 201;
971 : 202;
972 : 203;
973 : 204;
974 : 205;
975 : 206;
976 : 207;
977 : 208;
978 : 209;
979 : 210;
980 : 211;
981 : 212;
982 : 213;
983 : 214;
984 : 215;
985 : 216;
986 : 217;
987 : 218;
988 : 219;
989 : 220;
990 : 221;
991 : 222;
992 : 223;
993 : 224;
994 : 225;
995 : 226;
996 : 227;
997 : 228;
998 : 229;
999 : 230;
1000 : 231;
1001 : 232;
1002 : 233;
1003 : 234;
1004 : 235;
1005 : 236;
1006 : 237;
1007 : 238;
1008 : 239;
1009 : 240;
1010 : 241;
1011 : 242;
1012 : 243;
1013 : 244;
1014 : 245;
1015 : 246;
1016 : 247;
1017 : 248;
1018 : 249;
1019 : 250;
1020 : 251;
1021 : 252;
1022 : 253;
1023 : 254;
END;
3.顶层架构
红色箭头代表clk和rst_n,key_top模块包含三个按键的消抖处理,产生有效信号;ctrl_freq模块产生频率控制字,通过有限状态机将特定频率与状态绑定,通过按键切换状态,生成特定的频率控制字;addr_ctrl模块接收频率控制字产生读取地址;wave_ctrl对读取地址进行处理,通过有限状态机,对地址进行整体移位,进行波形切换;ampl_ctrl模块进行振幅控制,将读取的数据进行并位,倍数处理。
4.端口描述
clk | 时钟 |
rst_n | 复位按键 |
key_adjust | 切换波形按键 |
key_freq | 切换频率按键 |
key_ampl | 改变振幅按键 |
二、代码验证
wave_ctrl模块:对读取地址进行处理,通过有限状态机,对地址进行整体移位,进行波形切换;
module wave_ctrl(
input clk,
input rst_n,
input flag,//波形切换按键有效信号
input [7:0] addr,//输入的ROM地址
output reg [9:0] rom_addr//输出的ROM地址
);
reg [1:0] state;
parameter s0 = 2'd0;// 正弦[ 0: 255]
parameter s1 = 2'd1;// 方波[256: 511]
parameter s2 = 2'd2;//三角弦[512: 767]
parameter s3 = 2'd3;//锯齿弦[768:1023]
always @(posedge clk,negedge rst_n)//状态机进行地址切换
begin
if(rst_n == 0)
begin
state <= s0;
rom_addr <= 10'd0;
end
else
case(state)
s0 : begin
if(flag == 1)
begin
state <= s1;
rom_addr <= addr;
end
else
begin
state <= s0
rom_addr <= addr;
end
end
s1 : begin
if(flag == 1)
begin
state <= s2;
rom_addr <= addr + 10'd256;
end
else
begin
state <= s1;
rom_addr <= addr + 10'd256;
end
end
s2 : begin
rom_addr <= addr + 10'd512;
if(flag == 1)
state <= s3;
else
state <= s2;
end
s3 : begin
rom_addr <= addr + 10'd768;
if(flag == 1)
state <= s0;
else
state <= s3;
end
default : begin state <= s0; rom_addr <= 10'd0;end
endcase
end
endmodule
ctrl_freq模块:产生频率控制字,通过有限状态机将特定频率与状态绑定,通过按键切换状态,生成特定的频率控制字
module ctrl_freq(
input clk,
input rst_n,
input flag,//频率切换按键有效信号
output reg [31:0] fword//产生的频率控制字
);
reg [4:0] cnt;
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
cnt <= 5'd0;
else
if(flag == 1)
if(cnt < 19)
cnt <= cnt + 5'd1;
else
cnt <= 5'd0;
else
cnt <= cnt;
end
always @(*) begin
if(rst_n == 0)
fword <= 32'd0;
else
case(cnt)
5'd0 : fword <= 32'd4294967;//50khz
5'd1 : fword <= 32'd8589935;//100khz
5'd2 : fword <= 32'd12884902;//150khz
5'd3 : fword <= 32'd17179869;//200khz
5'd4 : fword <= 32'd21474836;//250khz
5'd5 : fword <= 32'd25769804;//300khz
5'd6 : fword <= 32'd30064771;//350khz
5'd7 : fword <= 32'd34359738;//400khz
5'd8 : fword <= 32'd38654706;//450khz
5'd9 : fword <= 32'd42949673;//500khz
5'd10 : fword <= 32'd47244640;//550khz
5'd11 : fword <= 32'd51539608;//600khz
5'd12 : fword <= 32'd55834575;//650khz
5'd13 : fword <= 32'd60129542;//700khz
5'd14 : fword <= 32'd64424509;//750khz
5'd15 : fword <= 32'd68719477;//800khz
5'd16 : fword <= 32'd73014444;//850khz
5'd17 : fword <= 32'd77309411;//900khz
5'd18 : fword <= 32'd81604379;//950khz
5'd19 : fword <= 32'd85899346;//1mhz
default : fword <= 32'd0;
endcase
end
endmodule
addr_ctrl模块:接收频率控制字产生读取地址;
module addr_ctrl(
input clk,
input rst_n,
input [31:0] fword,//频率控制字
output [7:0] addr//ROM需要的地址
);
reg [31:0] cnt;
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
cnt <= 32'd0;
else
cnt <= cnt + fword;
end
assign addr = cnt[31:24];
endmodule
ampl_ctrl模块:进行振幅控制,将读取的数据进行并位,倍数处理。
module ampl_ctrl(
input clk,
input rst_n,
input flag,
input [7:0] data,//ROM读出的数据
output reg [8:0] wave//并位后的数据
);
reg [3:0] cnt;
always @(posedge clk,negedge rst_n)//状态转换条件
begin
if(rst_n == 0)
cnt<= 4'd0;
else
if(flag == 1)
if(cnt < 8)
cnt <= cnt + 4'd1;
else
cnt<= 4'd0;
else
cnt <= cnt;
end
always @(*) begin
if(rst_n == 0)
wave <= 9'd0;
else
case(cnt)
4'd0 : wave <= data;
4'd1 : wave <= (data*(255 + 32))/255;//1.12倍
4'd2 : wave <= (data*(255 + 64))/255;//1.25倍
4'd3 : wave <= (data*(255 + 96))/255;//1.37倍
4'd4 : wave <= (data*(255 + 128))/255;//1.5倍
4'd5 : wave <= (data*(255 + 160))/255;//1.62倍
4'd6 : wave <= (data*(255 + 192))/255;//1.75倍
4'd7 : wave <= (data*(255 + 224))/255;//1.875倍
4'd8 : wave <= (data*(255 + 256))/255;//2倍
default : wave <= 9'd0;
endcase
end
endmodule
dds_wave模块:顶层模块
module dds_wave(
input clk,
input rst_n,
input key_adjust,//切换波形按键
input key_freq,//切换频率按键
input key_ampl,//改变振幅按键
output [8:0] wave
);
wire flag_adjust;
wire flag_freq;
wire flag_ampl;
wire [31:0] fword;
wire [7:0] addr;
wire [9:0] rom_addr;
wire [7:0] rom_data;
key_top key_top_inst(
.clk(clk),
.rst_n(rst_n),
.key_adjust(key_adjust),
.key_freq(key_freq),
.key_ampl(key_ampl),
.flag_adjust(flag_adjust),
.flag_freq(flag_freq),
.flag_ampl(flag_ampl)
);
ctrl_freq ctrl_freq_inst(
.clk(clk),
.rst_n(rst_n),
.flag(flag_freq),
.fword(fword)
);
addr_ctrl addr_ctrl_inst(
.clk(clk),
.rst_n(rst_n),
.fword(fword),
.addr(addr)
);
wave_ctrl wave_ctrl_inst(
.clk(clk),
.rst_n(rst_n),
.flag(flag_adjust),
.addr(addr),
.rom_addr(rom_addr)
);
wave_rom wave_rom_inst (
.address ( rom_addr ),
.clock ( clk ),
.q ( rom_data )
);
ampl_ctrl ampl_ctrl_inst(
.clk(clk),
.rst_n(rst_n),
.flag(flag_ampl),
.data(rom_data),
.wave(wave)
);
endmodule
jitter_ctrl模块:状态机进行按键消抖
//三段式
module jitter_ctrl_v2(
input clk,
input rst_n,
input key,
output reg flag,
output reg key_en
);
reg [3:0] n_state;
reg [3:0] c_state;
parameter s0 = 4'b0001;//空闲状态
parameter s1 = 4'b0010;//下抖动状态
parameter s2 = 4'b0100;//稳定状态
parameter s3 = 4'b1000;//上抖动状态
reg [3:0] cnt;
//FSM1
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
c_state <= s0;
else
c_state <= n_state;
end
//FSM2
always @(*)//描述状态转移
begin
if(rst_n == 0)
n_state <= s0;
else
case(c_state)
s0 : begin
if(key == 0)//默认按键低电平有效,即=0时按键按下
n_state <= s1;
else
n_state <= s0;
end
s1 : begin
if(cnt == 9)//延时计数器判断
n_state <= s2;
else
n_state <= s1;
end
s2 : begin
if(key == 1)//按键弹起,状态改变
n_state <= s3;
else
n_state <= s2;
end
s3 : begin
if(cnt == 9)//延时计数器判断
n_state <= s0;
else
n_state <= s3;
end
default : n_state <= s0;
endcase
end
//FSM3
always @(posedge clk,negedge rst_n)//状态输出产生flag信号
begin
if(rst_n == 0)
begin
cnt <= 4'd0;
flag <= 1'b0;
key_en <= 1'b0;
end
else
case(c_state)
s0 : begin
cnt <= 4'd0;
flag <= 1'b0;
key_en <= 1'b0;
end
s1 : begin
if(cnt < 9)//驱动延时计数器
cnt <= cnt + 4'd1;
else
cnt <= 4'd0;
if(cnt == 9)//延时计数器记满,产生flag
begin
flag <= 1'b1;//flag只产生一个时钟周期
key_en <= 1'b1; //输出使能
end
else
begin
key_en <= 1'b0;
flag <= 1'b0;
end
end
s2 : begin
flag <= 1'b0;
key_en <= 1'b1;
cnt <= 4'd0;
end
s3 : begin
flag <= 1'b0;//状态初始化,准备判断下次按键按下
key_en <= 1'b0;
if(cnt < 9)
cnt <= cnt + 4'd1;
else
cnt <= 4'd0;
end
default : begin
cnt <= 4'd0;
flag <= 1'b0;
key_en <= 1'b0;
end
endcase
end
endmodule
key_top模块:按键顶层
module key_top(
input clk,
input rst_n,
input key_adjust,
input key_freq,
input key_ampl,
output flag_adjust,
output flag_freq,
output flag_ampl
);
jitter_ctrl jitter_ctrl_inst1(
.clk(clk),
.rst_n(rst_n),
.key(key_adjust),
.flag(flag_adjust)
);
jitter_ctrl jitter_ctrl_inst2(
.clk(clk),
.rst_n(rst_n),
.key(key_freq),
.flag(flag_freq)
);
jitter_ctrl jitter_ctrl_inst3(
.clk(clk),
.rst_n(rst_n),
.key(key_ampl),
.flag(flag_ampl)
);
endmodule
仿真代码
`timescale 1ns/1ps
module dds_wave_tb;
reg clk;
reg rst_n;
reg key_adjust;
reg key_freq;
reg key_ampl;
wire [8:0] wave;
dds_wave dds_wave_inst(
.clk(clk),
.rst_n(rst_n),
.key_adjust(key_adjust),//切换波形按键
.key_freq(key_freq),//切换频率按键
.key_ampl(key_ampl),//改变振幅按键
.wave(wave)
);
initial clk = 1;
always #10 clk = ~clk;
initial begin
rst_n = 0;
key_adjust = 1;
key_freq = 1;
key_ampl = 1;
#200
rst_n = 1;
#40000
key_freq = 0;
#200
key_freq = 1;
#1000
key_freq = 0;
#200
key_freq = 1;
#1000
key_freq = 0;
#200
key_freq = 1;
#20000
key_adjust = 0;
#200
key_adjust = 1;
#20000
key_adjust = 0;
#200
key_adjust = 1;
#20000
key_adjust = 0;
#200
key_adjust = 1;
#20000
key_adjust = 0;
#200
key_adjust = 1;
#20000
key_ampl = 0;
#200
key_ampl = 1;
#20000
key_ampl = 0;
#200
key_ampl = 1;
#20000
key_ampl = 0;
#200
key_ampl = 1;
#20000
key_ampl = 0;
#200
key_ampl = 1;
#20000
$stop;
end
endmodule
三、仿真验证
运行仿真可以看到波形切换正确,频率切换也是可以的,后面正弦波振幅也是可以控制的
观察数据,初始没有按键操作,此时波形应该是正弦波,50Khz
1/(20000000ps)=50Khz,按下三次频率按键切换后理论上为200Khz
1/(5000000ps) =200Khz,频率切换成功,波形切换成功,下面探究振幅,初始正弦波最值255,,振幅切换按键按下一次后输出最值变为287,为1.12倍,再次按下输出最值变为319,为1.25倍。振幅切换成功。