-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
1022 lines (1020 loc) · 248 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Booth乘法器</title>
<url>/2021/12/14/booth%E4%B9%98%E6%B3%95%E5%99%A8/</url>
<content><![CDATA[<p>Booth算法乘法器</p>
<span id="more"></span>
<h1 id="乘法器分类">乘法器分类</h1>
<h2 id="传统乘法器">传统乘法器</h2>
<p> 传统乘法器的实现很简单,<strong>第一步</strong>就是去被乘数和乘数的正负关系然后去被乘数和乘数的正值;第二步:乘法本就是累加,乘多少就是累加多少次,所以第二步是累加操作,每加一次被乘数,递减一次乘数,直到乘数为0,表示操作结束;<strong>第三步</strong>:输出结果根据正负关系取得。</p>
<p> 乘法不是只对正数操作的,因此当乘法中有负数存在的时候我们可以先将乘积的符号结果记录下来,然后将含有负数的乘法转换成只有正数的乘法。FPGA中,整数都是由补码形式存储的(正数最高为为0,负数在高位为1),因此对符号的判断可以通过最高位的异或完成。</p>
<p> 为了使用更少的时钟计算出结果,既可以理解成 3 个 4 相加,也可以理解成 4 个 3 相加,但是 3 个 4 相加只用 3 个时钟周期,4 个 3 相加就需要 4 个时钟周期了,所以明显可以看出使用更小的数作为加法的轮数更省时。</p>
<h2 id="lut-乘法器">LUT 乘法器</h2>
<p> 查找表乘法器就是将乘法结果存储在一个表中,当需要完成乘法的时候直接从查找表中查找出乘积结果就可以了。</p>
<h1 id="booth乘法器">booth乘法器</h1>
<h2 id="booth乘法大致流程">booth乘法大致流程</h2>
<ol type="1">
<li><p>被乘数A,乘数B</p></li>
<li><p>将乘数B的末位加1位,即在B[-1]添加1位加码。</p>
<table>
<thead>
<tr class="header">
<th>……</th>
<th>B[0]</th>
<th>B[-1]</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>……</td>
<td>0</td>
<td>0</td>
<td>无操作 右移1位</td>
</tr>
<tr class="even">
<td>......</td>
<td>0</td>
<td>1</td>
<td>+被乘数A 右移1位</td>
</tr>
<tr class="odd">
<td>......</td>
<td>1</td>
<td>0</td>
<td>-被乘数A 右移1位</td>
</tr>
<tr class="even">
<td>......</td>
<td>1</td>
<td>1</td>
<td>无操作 右移1位</td>
</tr>
</tbody>
</table></li>
<li><p>P空间 在位操作时,会使用<span class="math inline">\(P\)</span>空间,容量为<span class="math inline">\(2n+1\)</span>,<span class="math inline">\(n\)</span>为乘数和被乘数的位数(根据不同情况<span class="math inline">\(n\)</span>值不同)。</p>
<h2 id></h2></li>
</ol>
<link rel="stylesheet" href="/css/spoiler.css" type="text/css"><script src="/js/spoiler.js" type="text/javascript" async></script>]]></content>
<categories>
<category>FPGA</category>
<category>Verilog</category>
<category>Booth乘法器</category>
</categories>
<tags>
<tag>Booth乘法器</tag>
</tags>
</entry>
<entry>
<title>快速傅里叶变换(FFT)</title>
<url>/2021/11/04/DFT-FFT/</url>
<content><![CDATA[<p>快速傅里叶变换(FFT) <span id="more"></span></p>
<h1 id="dft离散傅里叶变换">DFT(离散傅里叶变换)</h1>
<p> 一个信号,不是连续的就是离散的,不是周期的就是非周期的,其傅里叶变换如下:</p>
<ul>
<li><strong>连续-周期</strong>信号的FT叫做<strong>傅里叶级数</strong></li>
<li><strong>连续-非周</strong>期信号的FT叫做<strong>傅里叶变换</strong></li>
<li><strong>离散-周期</strong>信号的FT叫做<strong>离散傅里叶变换</strong> DFT</li>
<li><strong>离散-非周期</strong>信号的FT叫做<strong>离散时间傅里叶变换</strong> DTFT</li>
</ul>
<p> DFT的本质是将离散的时域序列用有限个余弦波和正弦波合成。比如一个32点的时域序列,可以用17个余弦波和17个正弦波合成。17个余弦波的幅值就是频谱的实部,17个正弦波的幅值就是频谱的虚部。要从从离散时域序列中“找到”这17个余弦波或者正弦波。通过做互相关。把原始时域序列和某一频率的余弦波或者余弦波做相关,如果值等于0,说明原始时域序列中不包含该频率的余弦波或者正弦波,因此这个时域序列的频谱中,该频率的虚部或者实部是0。如果值等于,比如说32,那么时域序列的频谱中,该频率余弦波或者正弦波的幅值就是32。</p>
<p> 简而言之,DFT就是:<strong>在长度为N的离散信号中,针对k=(0,1,2...),分别找出在长度N内振动k个周期的三角波分量的权值。</strong>离散傅里叶变换公式如下: <span class="math display">\[
X(K)=DFT\lbrace x(n) \rbrace = \sum_{n=0}^{N-1}x(n)\cdot e^{-j{\frac{2\pi}{N}}nk}\tag{1} \label{eq1}
\]</span></p>
<p> 对一个离散信号中的一个点进行DFT计算需要进行<span class="math inline">\(N\)</span>次乘法运算和<span class="math inline">\(N-1\)</span>次加法运算,如果计算整个序列的DFT则需要进行<span class="math inline">\(N^2\)</span>次乘法和<span class="math inline">\(N \cdot (N-1)\)</span>次加法运算。因此需要对计算过程进行优化。</p>
<h1 id="fft快速傅里叶变换">FFT(快速傅里叶变换)</h1>
<p> DFT的定义式<span class="math inline">\(\eqref{eq1}\)</span>中含有<span class="math inline">\(e^{-j{\frac{2\pi}{N}}nk}\)</span>项,它具有很多性质,令<span class="math inline">\(e^{-j{\frac{2\pi}{N}}nk}=W_{N}^{nk}\)</span> ,其中<span class="math inline">\(W_{N}^{nk}\)</span>称为旋转因子(<span class="math inline">\(W_{N}^{0}=1\)</span>)。则可将DFT定义式写为: <span class="math display">\[
X(K)=DFT\lbrace x(n) \rbrace = \sum_{n=0}^{N-1}x(n)\cdot W_{N}^{nk}\tag{2} \label{eq2}
\]</span></p>
<h2 id="旋转因子w_nnk">旋转因子<span class="math inline">\(W_{N}^{nk}\)</span></h2>
<p><span class="math inline">\(W_{N}^{nk}\)</span>具有以下性质:</p>
<p>1.周期性 <span class="math display">\[
W_{N}^{m+LN}=W_{N}^{m}
\]</span> 2.对称性 <span class="math display">\[
W_{N}^{m+{\frac{N}{2}}}=-W_{N}^{m}
\]</span> 3.可约性 <span class="math display">\[
W_{N/m}^{k}=-W_{N}^{mk}
\]</span> 按我的理解,这些性质完全不用去记,直接将<span class="math inline">\(W_{N}^{nk}\)</span>看作为一个单位圆,按弧长被分为<span class="math inline">\(N\)</span>份<span class="math inline">\(nk\)</span>则是逆时针从正半轴零轴逆时针转动<span class="math inline">\(nk\)</span>的长度。所以其周期为<span class="math inline">\(N\)</span>。</p>
<h2 id="dit-fft数学推导">DIT-FFT数学推导</h2>
<p>对序列<span class="math inline">\(x(n)\)</span>的第K个点进行一次抽取: <span class="math display">\[
\begin{flalign}
X(k)&=\sum_{n=0}^{N-1}{x(n)W_{N}^{nk}} \nonumber \\
&= \sum_{n=0,2,4...}^{N-1}{x(n)W_{N}^{nk}}+\sum_{n=1,3,5...}^{N-1}{x(n)W_{N}^{nk}} \overset{\text{n=2r}}{\longrightarrow}\nonumber \\
&=\sum_{n=0,1,2...}^{N/2-1}{x(2r)W_{N}^{2rk}}+\sum_{n=0,1,2...}^{N/2-1}{x(2r+1)W_{N}^{(2r+1)k}}\overset{\text{令x(2r)=X1(r);x(2r+1)=X2(r)}}{\longrightarrow}\nonumber \\
&= \sum_{n=0,1,2...}^{N/2-1}{x_{1}(r)W_{N}^{2rk}}+\sum_{n=0,1,2...}^{N/2-1}{x_{2}
(r)W_{N}^{(2r+1)k}}\text{通过旋转因子的性质化简}\nonumber \\
&=\sum_{n=0,1,2...}^{N/2-1}{x_{1}(r)W_{N/2}^{rk}}+W_{N}^{nk}\cdot\sum_{n=0,1,2...}^{N/2-1}{x_{2}(r)W_{N/2}^{rk}}\nonumber \\
X(k)&=X_{1}(k)+W_{N}^{nk}X_2(k)\nonumber
\end{flalign}
\tag{3} \label{eq3}
\]</span> 再将<span class="math inline">\(X(k)\)</span>通过旋转因子<span class="math inline">\(W_{N}^{nk}\)</span>的周期性得到<span class="math inline">\(X(k+\frac{N}{2})=X_1(k)-W_{N}^{k}X_2(k)\)</span>。在对<span class="math inline">\(\eqref{eq3}中的\)</span><span class="math inline">\(X_1(k)\)</span>和<span class="math inline">\(X_2(k)\)</span>进行相同的分解,得到: <span class="math display">\[
\left.
\begin{flalign}
X_1(k)&=X_{3}(k)+W_{N/2}^{nk}X_4(k)\nonumber\\
X_1(k+\frac{N}{4})&=X_{3}(k)-W_{N/2}^{nk}X_4(k)\nonumber
\end{flalign}
\right\}蝶形组合(0\leq k \leq \frac{N}{4}-1 )
\tag{4} \label{eq4}
\]</span></p>
<p><span class="math display">\[
\left.
\begin{flalign}
X_2(k)&=X_{5}(k)+W_{N/2}^{nk}X_6(k)\nonumber\\
X_2(k+\frac{N}{4})&=X_{5}(k)-W_{N/2}^{nk}X_6(k)\nonumber
\end{flalign}
\right\}蝶形组合(0\leq k \leq \frac{N}{4}-1 )
\tag{5} \label{eq5}
\]</span></p>
<p> 持续将其分解,直到分解到输入部分是码位倒序后的N/2个2点序列,假设其中一个2点序列为:<span class="math inline">\(x(k_1),x(k_2)\)</span>,则最后一级分解的蝶形运算公式为: <span class="math display">\[
\left.
\begin{flalign}
X_{2^N-1}(k)&=X(k_1)+X(k_2)\nonumber\\
X_{2^N-1}(k+\frac{N}{k})&=X(k_1)-X(k_2)\nonumber
\end{flalign}
\right\}蝶形组合(k=0)
\tag{6} \label{eq6}
\]</span> 下图为当N=8时候的蝶形图:</p>
<figure>
<img src="/2021/11/04/DFT-FFT/蝶形图.jpg" alt="蝶形图"><figcaption aria-hidden="true">蝶形图</figcaption>
</figure>
<center style="color:#4F4F4F">
图1-8点fft运算图
</center>
<h1 id="fft算法流程c语言">FFT算法流程(C语言)</h1>
<h2 id="码位倒序">码位倒序</h2>
<p> 基2的DIF和DIT的FFT都需要进行码位倒序,区别是一个是输入前需要(DIT),一个是输出前需要(DIF)。从C语言的角度来说按2进制进行位的互换是比通过Verilog要复杂得多,主要思路是通过数组下标2进制码位的前半部分和后半部分进行比较,之后数组下标的互换。下面是C语言的代码:</p>
<figure class="highlight c"><table><tbody><tr><td class="code"><pre><span class="line"> <span class="comment">//倒序</span></span><br><span class="line"><span class="keyword">for</span>(I=<span class="number">0</span>;I<N;I++) <span class="comment">//对数组元素执行码间倒序</span></span><br><span class="line">{ </span><br><span class="line"> <span class="comment">/*获取下标I的反序J的数值*/</span> </span><br><span class="line"> J=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(k=<span class="number">0</span>;k<(M/<span class="number">2</span>+<span class="number">0.5</span>);k++) <span class="comment">//k表示操作</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">//*反序操作*/</span></span><br><span class="line"> m=<span class="number">1</span>;<span class="comment">//m是最低位为1的二进制数</span></span><br><span class="line"> n=(<span class="keyword">unsigned</span> <span class="keyword">int</span>)<span class="built_in">pow</span>(<span class="number">2</span>,M<span class="number">-1</span>);<span class="comment">//n是第M位为1的二进制数</span></span><br><span class="line"> m <<= k; <span class="comment">//对m左移k位</span></span><br><span class="line"> n >>= k; <span class="comment">//对n右移k位</span></span><br><span class="line"> F0=I & n;<span class="comment">//I与n按位与提取出前半部分第k位</span></span><br><span class="line"> F1=I & m;<span class="comment">//I与m按位与提取出F0对应的后半部分的低位</span></span><br><span class="line"> <span class="keyword">if</span>(F0) J=J | m; <span class="comment">//J与m按位或使F0对应低位为1</span></span><br><span class="line"> <span class="keyword">if</span>(F1) J=J | n; <span class="comment">//J与n按位或使F1对应高位为1 </span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//printf("I为:");printBin(I,M);printf(" %d\n",I);</span></span><br><span class="line"> <span class="comment">//printf("J为:");printBin(J,M);printf(" %d\n\n",J);</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span>(I<J)</span><br><span class="line"> {</span><br><span class="line"> temp = dataR[I];</span><br><span class="line"> dataR[I] = dataR[J];</span><br><span class="line"> dataR[J] = temp;</span><br><span class="line"> <span class="comment">//补充虚数部分交换: </span></span><br><span class="line"> temp = dataI[I];</span><br><span class="line"> dataI[I] = dataI[J];</span><br><span class="line"> dataI[J] = temp;</span><br><span class="line"> } </span><br><span class="line">} </span><br></pre></td></tr></tbody></table></figure>
<h2 id="蝶形运算设计">蝶形运算设计</h2>
<p><img src="/2021/11/04/DFT-FFT/蝶形图3.jpg"></p>
<center style="color:#4F4F4F">
图2-16点fft运算图
</center>
<p>说明:</p>
<p>1)L代表某一级,(L=1,2,3…M)</p>
<p>2)旋转因子记为:<span class="math inline">\(W_N^p\)</span> ,p是旋转因子指数,P相同则为同一种旋转因子。</p>
<p>3)旋转因子的增量记为:k,在M级(最后一级)增量k总为1。</p>
<p>4)B表示每个蝶形运算的两个输入数据的间隔。</p>
<p>通过对蝶形图的观察,得到如下的规律(在第<span class="math inline">\(L\)</span>级中):</p>
<ol type="1">
<li>每个蝶形运算中两个输入数据的间数<span class="math inline">\(B=2^{L-1}\)</span>。</li>
<li>有<span class="math inline">\(2^{L-1}\)</span>个旋转因子。</li>
<li>旋转因子<span class="math inline">\(W\)</span>增量为<span class="math inline">\(k=2^{M-L}\)</span>。</li>
<li>同一<span class="math inline">\(W\)</span>的间隔为:<span class="math inline">\(2^{L}=2*B\)</span>。</li>
<li>蝶形运算的种类数目<span class="math inline">\(=\)</span>间隔<span class="math inline">\(B=2^{L-1}\)</span>。</li>
<li>同种蝶形运算次数<span class="math inline">\(=k=2^{M-L}\)</span>。</li>
</ol>
<p>下面给出C语言FFT代码:</p>
<figure class="highlight c++"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">for</span>(L=<span class="number">1</span>; L<=M;L++) <span class="comment">//FFT蝶形级数L从1--M</span></span><br><span class="line">{ </span><br><span class="line"> <span class="comment">/*第L级的运算*/</span> </span><br><span class="line"> <span class="comment">//先计算间隔 B = 2^(L-1);</span></span><br><span class="line"> B = <span class="number">1</span>;</span><br><span class="line"> B = (<span class="keyword">int</span>)<span class="built_in">pow</span>(<span class="number">2</span>,L<span class="number">-1</span>);</span><br><span class="line"> <span class="keyword">for</span>(j=<span class="number">0</span>; j<=B<span class="number">-1</span>;j++)</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">/*同种蝶形运算*/</span> </span><br><span class="line"> <span class="comment">//先计算增量k=2^(M-L)</span></span><br><span class="line"> k = (<span class="keyword">int</span>)<span class="built_in">pow</span>(<span class="number">2</span>,M-L);</span><br><span class="line"> <span class="comment">//计算旋转指数p,增量为k时,则P=j*k</span></span><br><span class="line"> P=<span class="number">1</span>;</span><br><span class="line"> P=j*k;</span><br><span class="line"> <span class="keyword">for</span>(i=<span class="number">0</span>; i<=k<span class="number">-1</span>;i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">/*进行蝶形运算*/</span></span><br><span class="line"> <span class="comment">//数组下标定为r</span></span><br><span class="line"> r=<span class="number">1</span>;</span><br><span class="line"> r=j+<span class="number">2</span>*B*i;</span><br><span class="line"> Tr=dataR[r+B]*<span class="built_in">cos</span>(<span class="number">2.0</span>*PI*p/N) + dataI[r+B]*<span class="built_in">sin</span>(<span class="number">2.0</span>*PI*p/N);</span><br><span class="line"> Ti=dataI[r+B]*<span class="built_in">cos</span>(<span class="number">2.0</span>*PI*p/N) - dataR[r+B]*<span class="built_in">sin</span>(<span class="number">2.0</span>*PI*p/N);</span><br><span class="line"> dataR[r+B]=dataR[r]-Tr;</span><br><span class="line"> dataI[r+B]=dataI[r]-Ti;</span><br><span class="line"> dataR[r]=dataR[r]+Tr;</span><br><span class="line"> dataI[r]=dataI[r]]+Ti;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>
<h2 id="c语言与matlab结果对比">C语言与matlab结果对比</h2>
<p>输入信号为</p>
<figure class="highlight matlab"><table><tbody><tr><td class="code"><pre><span class="line">N = <span class="number">128</span>,A0 = <span class="number">255</span>;PI = <span class="number">3.1415926</span>;</span><br><span class="line"><span class="built_in">i</span> = <span class="number">1</span>:N;</span><br><span class="line">x = A0*(<span class="built_in">sin</span>((PI/<span class="number">4</span>)+<span class="number">2</span>*PI*<span class="built_in">i</span>/<span class="number">50</span>)+<span class="built_in">cos</span>(<span class="number">2</span>*PI* <span class="built_in">i</span>/<span class="number">10</span> ));</span><br></pre></td></tr></tbody></table></figure>
<p><img src="/2021/11/04/DFT-FFT/fft对比.jpg"></p>
<p><img src="/2021/11/04/DFT-FFT/ifft对比.jpg"></p>
<center style="color:#4F4F4F">
图3-C语言matlab结果对比
</center>
<h1 id="fft-verilog设计思路">FFT-verilog设计思路</h1>
<h2 id="流水线级联架构">流水线级联架构</h2>
<p> 流水线级联架构的流程图如图 所示,这种方式采用了多级蝶形运算的思想,器处理的方式和顺序的处理方式,但是每一级的蝶形运算由各自的蝶形运算模块负责运算并且需要相应的存储模块与其配合工作,每一级的蝶形运算模块负责计算该级的全部蝶形运算也就是 <span class="math inline">\(N/2\)</span> 次,处理的方式和顺序递归是相同的,在此基础上通过流水线的插入使得处理连续的输入序列时,整个处理器的计算周期大大减少,速度提高了<span class="math inline">\(log_2 N\)</span> 倍,每当一级的运算结束之后,结果送入下一级的蝶形运算模块,而此时该级又能对下一组的数据进行运算,相应的这种架构的实现需要付出资源消耗的代价,但是针对移动端该方法可以降低系统功耗。</p>
<p> 数据通过每一级的蝶形运算最终产生输出,同种所示的模式选择既是扩展点数的模式选择,该种架构更有利于 FFT 处理器的点数扩张和移植,针对不同点数的 FFT 所需要的蝶形运算模块的级数是不同的,例如 32 点需要 5 级,64 点需要6级。我们可以在设计中预留一部分的蝶形运算模块,当需要点数扩充的时候,我们可以通过模式的选择来增加蝶形运算模块的级数,同理当我们需要减小点数时则可以通过这种方法来缩小蝶形运算模块的级数,由于这种方式需要数量较多的蝶形运算模块,所以该方法更适用于大点数序列以及实时性要求较高的FFT 变换。</p>
<p><img src="/2021/11/04/DFT-FFT/流水线级联架构.png"></p>
<center style="color:#4F4F4F">
图4-流水线级联架构的流程图
</center>
<h2 id="阵列结构">阵列结构</h2>
<p> 阵列结构的思想是为处理器配备所有需要的蝶形运算模块,虽然资源消耗过大,但运算速度却高很多,因为此次只是验证fft算法,以及数据定点,所以选择此结构,并实现基2-8点-fft。</p>
<p> <img src="/2021/11/04/DFT-FFT/阵列结构.png"></p>
<center style="color:#4F4F4F">
图5-阵列架构的流程图
</center>
<h1 id="verilog实现radix-2_128_fft">Verilog实现(Radix-2_128_fft)</h1>
<h2 id="数据定点">数据定点</h2>
<p> 128点的fft需要64个旋转因子,将旋转因子的字长定为16位,通过matlab计算出后,将其扩大8192倍(<span class="math inline">\(2^{13}\)</span>),再将其转化为16位16进制数。matlab代码如下:</p>
<figure class="highlight matlab"><table><tbody><tr><td class="code"><pre><span class="line">clear all;close all;clc;</span><br><span class="line"><span class="comment">%=======================================================</span></span><br><span class="line"><span class="comment">% Wnr calcuting</span></span><br><span class="line"><span class="comment">%=======================================================</span></span><br><span class="line">N = <span class="number">128</span>;</span><br><span class="line"><span class="keyword">for</span> r = <span class="number">0</span>:<span class="number">63</span></span><br><span class="line"> Wnr_factor = <span class="built_in">cos</span>(<span class="number">2</span>*<span class="built_in">pi</span>*r/N) - <span class="number">1</span><span class="built_in">i</span>*<span class="built_in">sin</span>(<span class="number">2</span>*<span class="built_in">pi</span>*r/N);</span><br><span class="line"> Wnr_integer = <span class="built_in">floor</span>(Wnr_factor * <span class="number">2</span>^<span class="number">13</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">real</span>(Wnr_integer)<<span class="number">0</span>)</span><br><span class="line"> Wnr_real = <span class="built_in">real</span>(Wnr_integer) + <span class="number">2</span>^<span class="number">16</span>; <span class="comment">%负数的补码</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> Wnr_real = <span class="built_in">real</span>(Wnr_integer); </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">imag</span>(Wnr_integer)<<span class="number">0</span>)</span><br><span class="line"> Wnr_imag = <span class="built_in">imag</span>(Wnr_integer) + <span class="number">2</span>^<span class="number">16</span>; </span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> Wnr_imag = <span class="built_in">imag</span>(Wnr_integer);</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> Wnr_real_r(r+<span class="number">1</span>,:) = Wnr_real;</span><br><span class="line"> Wnr_imag_r(r+<span class="number">1</span>,:) = Wnr_imag;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">Wnr_real_r = dec2hex(Wnr_real_r) <span class="comment">%实部</span></span><br><span class="line">Wnr_imag_r = dec2hex(Wnr_imag_r) <span class="comment">%虚部</span></span><br></pre></td></tr></tbody></table></figure>
<p>输出结果大致如下:</p>
<p><img src="/2021/11/04/DFT-FFT/image-20211225184431507.png" style="zoom: 80%;"><img src="/2021/11/04/DFT-FFT/image-20211225184551851.png" style="zoom:67%;"></p>
<center style="color:#4F4F4F">
图6-生成旋转因子
</center>
<p> 将旋转因子定点后,将输入的数据大小定为24位,输出数据大小定为24位。我们采用定点数的方法来计算数值,虽然定点运算能不用额外的资源来实现,但是比较容易引入误差和溢出,为了确保数据在运算中不会发生溢出并确保数据的计算精度,一般有两种方法:</p>
<ol type="1">
<li><p>我们需要对输入的数据进行扩位操作,也就是每一次的计算之前对数据进行扩展,这种方法可以确保数据的精度,缺点就是占用资源;</p></li>
<li><p>另外一种方法是对参与计算的数据进行移位操作,每次计算前都将数据左移一位来避免溢出,这种方法占用资源少,所以我们选择此方案作为防止数据运算中溢出的方法。</p></li>
</ol>
<h2 id="蝶形运算单元">蝶形运算单元</h2>
<p> 由于采用的是按时间抽取的fft,所以蝶形运算部分按下图设计:</p>
<p><img src="/2021/11/04/DFT-FFT/image-20211227110812307.png"></p>
<center style="color:#4F4F4F">
图7-蝶形运算单元
</center>
<p> 由于前面使用matlab生成的旋转因子扩大了<span class="math inline">\(2^{13}=8192\)</span>倍,为了防止蝶形运算中的乘法和加法导致位宽逐级增大,每一级运算完成后,要对输出数据进行固定位宽的截位,也可去掉旋转因子倍数增大而带来的影响。所以在模块最后输出的时候将低位的13位舍弃,只选取剩下的高位数据。设计代码如下:</p>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="meta">`<span class="meta-keyword">timescale</span> 1ns/1ps</span></span><br><span class="line"><span class="comment">/*********************** unit ******************************</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">Xm(p) ------------------------> Xm+1(p)</span></span><br><span class="line"><span class="comment"> - -></span></span><br><span class="line"><span class="comment"> - -</span></span><br><span class="line"><span class="comment"> -</span></span><br><span class="line"><span class="comment"> - -</span></span><br><span class="line"><span class="comment"> - -></span></span><br><span class="line"><span class="comment">Xm(q) ------------------------> Xm+1(q)</span></span><br><span class="line"><span class="comment"> Wn -1</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span><span class="comment">////////////////////////////////////////////////////////////////</span></span><br><span class="line"><span class="keyword">module</span> butterfly</span><br><span class="line"> (</span><br><span class="line"> <span class="keyword">input</span> clk,</span><br><span class="line"> <span class="keyword">input</span> rstn,</span><br><span class="line"> <span class="keyword">input</span> en,</span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] xp_real, <span class="comment">// Xm(p)</span></span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] xp_imag,</span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] xq_real, <span class="comment">// Xm(q)</span></span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] xq_imag,</span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">15</span>:<span class="number">0</span>] factor_real, <span class="comment">// Wnr</span></span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">15</span>:<span class="number">0</span>] factor_imag,</span><br><span class="line"></span><br><span class="line"> <span class="keyword">output</span> valid,</span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] yp_real, <span class="comment">//Xm+1(p)</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] yp_imag,</span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] yq_real, <span class="comment">//Xm+1(q)</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] yq_imag);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">reg</span> [<span class="number">4</span>:<span class="number">0</span>] en_r ;</span><br><span class="line"> <span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rstn) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (!rstn) <span class="keyword">begin</span></span><br><span class="line"> en_r <= <span class="number">'b0</span> ;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">begin</span></span><br><span class="line"> en_r <= {en_r[<span class="number">3</span>:<span class="number">0</span>], en} ;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment">借助 matlab 将旋转因子扩大 8192 倍(左移 13 位)</span></span><br><span class="line"><span class="comment">为了防止蝶形运算中的乘法和加法导致位宽逐级增大,每一级运算完成后,</span></span><br><span class="line"><span class="comment">要对输出数据进行固定位宽的截位,也可去掉旋转因子倍数增大而带来的影响。 </span></span><br><span class="line"><span class="comment">*/</span> <span class="comment">//================================================================================//</span></span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xq_wnr_real0;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xq_wnr_real1;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xq_wnr_imag0;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xq_wnr_imag1;</span><br><span class="line"> <span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] wire_xq_wnr_real0;</span><br><span class="line"> <span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] wire_xq_wnr_real1;</span><br><span class="line"> <span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] wire_xq_wnr_imag0;</span><br><span class="line"> <span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] wire_xq_wnr_imag1;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xp_real_d;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xp_imag_d;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> MULT mult_xq_wnr_real0(</span><br><span class="line"> <span class="variable">.clk</span> (clk) ,</span><br><span class="line"> <span class="variable">.rstn</span> (rstn) ,</span><br><span class="line"> <span class="variable">.a</span> (xq_real),</span><br><span class="line"> <span class="variable">.b</span> (factor_real),</span><br><span class="line"> <span class="variable">.z</span> (wire_xq_wnr_real0)</span><br><span class="line"> );</span><br><span class="line"> </span><br><span class="line"> MULT mult_xq_wnr_real1(</span><br><span class="line"> <span class="variable">.clk</span> (clk) ,</span><br><span class="line"> <span class="variable">.rstn</span> (rstn) ,</span><br><span class="line"> <span class="variable">.a</span> (xq_imag),</span><br><span class="line"> <span class="variable">.b</span> (factor_imag),</span><br><span class="line"> <span class="variable">.z</span> (wire_xq_wnr_real1)</span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> MULT mult_xq_wnr_imag0(</span><br><span class="line"> <span class="variable">.clk</span> (clk) ,</span><br><span class="line"> <span class="variable">.rstn</span> (rstn) ,</span><br><span class="line"> <span class="variable">.a</span> (xq_real),</span><br><span class="line"> <span class="variable">.b</span> (factor_imag),</span><br><span class="line"> <span class="variable">.z</span> (wire_xq_wnr_imag0)</span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> MULT mult_xq_wnr_imag1(</span><br><span class="line"> <span class="variable">.clk</span> (clk) ,</span><br><span class="line"> <span class="variable">.rstn</span> (rstn) ,</span><br><span class="line"> <span class="variable">.a</span> (xq_imag),</span><br><span class="line"> <span class="variable">.b</span> (factor_real),</span><br><span class="line"> <span class="variable">.z</span> (wire_xq_wnr_imag1)</span><br><span class="line"> ); </span><br><span class="line"></span><br><span class="line"> <span class="keyword">always</span> @(*) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (!rstn) <span class="keyword">begin</span></span><br><span class="line"> xq_wnr_real0 = <span class="number">'b0</span>;</span><br><span class="line"> xq_wnr_real1 = <span class="number">'b0</span>;</span><br><span class="line"> xq_wnr_imag0 = <span class="number">'b0</span>;</span><br><span class="line"> xq_wnr_imag1 = <span class="number">'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">begin</span></span><br><span class="line"> xq_wnr_real0 = wire_xq_wnr_real0;</span><br><span class="line"> xq_wnr_real1 = wire_xq_wnr_real1;</span><br><span class="line"> xq_wnr_imag0 = wire_xq_wnr_imag0;</span><br><span class="line"> xq_wnr_imag1 = wire_xq_wnr_imag1;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rstn) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (!rstn) <span class="keyword">begin</span></span><br><span class="line"> xp_real_d <= <span class="number">'b0</span>;</span><br><span class="line"> xp_imag_d <= <span class="number">'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (en) <span class="keyword">begin</span></span><br><span class="line"> xp_real_d <= {{<span class="number">4</span>{xp_real[<span class="number">23</span>]}}, xp_real[<span class="number">22</span>:<span class="number">0</span>], <span class="number">13'b0</span>} ; <span class="comment">// Wnr扩展14bit</span></span><br><span class="line"> xp_imag_d <= {{<span class="number">4</span>{xp_imag[<span class="number">23</span>]}}, xp_imag[<span class="number">22</span>:<span class="number">0</span>], <span class="number">13'b0</span>} ;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xp_real_d1;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xp_imag_d1;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xq_wnr_real;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] xq_wnr_imag;</span><br><span class="line"> <span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rstn) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (!rstn) <span class="keyword">begin</span></span><br><span class="line"> xp_real_d1 <= <span class="number">'b0</span>;</span><br><span class="line"> xp_imag_d1 <= <span class="number">'b0</span>;</span><br><span class="line"> xq_wnr_real <= <span class="number">'b0</span> ;</span><br><span class="line"> xq_wnr_imag <= <span class="number">'b0</span> ;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (en_r[<span class="number">0</span>]) <span class="keyword">begin</span></span><br><span class="line"> xp_real_d1 <= xp_real_d;</span><br><span class="line"> xp_imag_d1 <= xp_imag_d;</span><br><span class="line"> <span class="comment">//提前设置好位宽余量,防止数据溢出</span></span><br><span class="line"> xq_wnr_real <= xq_wnr_real0 - xq_wnr_real1 ; </span><br><span class="line"> xq_wnr_imag <= xq_wnr_imag0 + xq_wnr_imag1 ;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span> <span class="comment">//======================================================================</span></span><br><span class="line"> <span class="comment">//(2.0) 蝶形运算结果输出</span></span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] yp_real_r;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] yp_imag_r;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] yq_real_r;</span><br><span class="line"> <span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] yq_imag_r;</span><br><span class="line"> <span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rstn) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (!rstn) <span class="keyword">begin</span></span><br><span class="line"> yp_real_r <= <span class="number">'b0</span>;</span><br><span class="line"> yp_imag_r <= <span class="number">'b0</span>;</span><br><span class="line"> yq_real_r <= <span class="number">'b0</span>;</span><br><span class="line"> yq_imag_r <= <span class="number">'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (en_r[<span class="number">1</span>]) <span class="keyword">begin</span></span><br><span class="line"> yp_real_r <= xp_real_d1 + xq_wnr_real;</span><br><span class="line"> yp_imag_r <= xp_imag_d1 + xq_wnr_imag;</span><br><span class="line"> yq_real_r <= xp_real_d1 - xq_wnr_real;</span><br><span class="line"> yq_imag_r <= xp_imag_d1 - xq_wnr_imag;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">assign</span> valid = en_r[<span class="number">2</span>];</span><br><span class="line"> <span class="keyword">always</span> @(*) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (!rstn) <span class="keyword">begin</span></span><br><span class="line"> yp_real = <span class="number">'b0</span>;</span><br><span class="line"> yp_imag = <span class="number">'b0</span>;</span><br><span class="line"> yq_real = <span class="number">'b0</span>;</span><br><span class="line"> yq_imag = <span class="number">'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">begin</span></span><br><span class="line"> yp_real = {yp_real_r[<span class="number">39</span>], yp_real_r[<span class="number">13</span>+<span class="number">23</span>:<span class="number">13</span>]};</span><br><span class="line"> yp_imag = {yp_imag_r[<span class="number">39</span>], yp_imag_r[<span class="number">13</span>+<span class="number">23</span>:<span class="number">13</span>]};</span><br><span class="line"> yq_real = {yq_real_r[<span class="number">39</span>], yq_real_r[<span class="number">13</span>+<span class="number">23</span>:<span class="number">13</span>]};</span><br><span class="line"> yq_imag = {yq_imag_r[<span class="number">39</span>], yq_imag_r[<span class="number">13</span>+<span class="number">23</span>:<span class="number">13</span>]};</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">endmodule</span></span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure>
<h2 id="booth乘法器模块">Booth乘法器模块</h2>
<h3 id="booth乘法大致流程">booth乘法大致流程</h3>
<ol type="1">
<li><p>被乘数A,乘数B</p></li>
<li><p>将乘数B的末位加1位,即在B[-1]添加1位加码。</p>
<table>
<thead>
<tr class="header">
<th>……</th>
<th>B[0]</th>
<th>B[-1]</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>……</td>
<td>0</td>
<td>0</td>
<td>无操作 右移1位</td>
</tr>
<tr class="even">
<td>......</td>
<td>0</td>
<td>1</td>
<td>+被乘数A 右移1位</td>
</tr>
<tr class="odd">
<td>......</td>
<td>1</td>
<td>0</td>
<td>-被乘数A 右移1位</td>
</tr>
<tr class="even">
<td>......</td>
<td>1</td>
<td>1</td>
<td>无操作 右移1位</td>
</tr>
</tbody>
</table></li>
<li><p>P空间 在位操作时,会使用<span class="math inline">\(P\)</span>空间,容量为<span class="math inline">\(2n+1\)</span>,<span class="math inline">\(n\)</span>为乘数和被乘数的位数(根据不同情况<span class="math inline">\(n\)</span>值不同)。</p></li>
</ol>
<h3 id="算法示例">算法示例</h3>
<ol type="1">
<li>设被乘数A=7=[0111];乘数B=2=[0010];对应的-A和-B为[1011]和[1110] ,(A,B都为4bit)。</li>
<li>将P设为[8:0]=0000_0000_0。</li>
<li>将乘数B填入P的[4:1],--->P[8:0]=0000_0010_0。</li>
<li>判断P[1:0],为2'b00,--->无操作。再将P右移1位--->p[8:0]=0000_0001_0。</li>
<li>判断P[1:0],为2'b10,--->减去被乘数,即P[8:5]减去A--->p[8:0]=1001_0001_0。再将P右移1位--->p[8:0]=1100_1000_1。</li>
<li>判断P[1:0],为2'b01,--->加被乘数,即P[8:5]加上A--->p[8:0]=0011_1000_1。再将P右移1位--->p[8:0]=0001_1100_0。</li>
<li>判断P[1:0],为2'b00,--->无操作。再将P右移1位--->p[8:0]=0000_1110_0。</li>
</ol>
<p>循环操作4次后结束,此时P中的值为A*B=14。</p>
<h3 id="代码实现">代码实现</h3>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="meta">`<span class="meta-keyword">timescale</span> 1ns / 1ps</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> MULT(</span><br><span class="line"> <span class="keyword">input</span> clk, <span class="comment">// 乘法器时钟信号</span></span><br><span class="line"> <span class="keyword">input</span> rstn,</span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] a, <span class="comment">// 输入 a(被乘数 )</span></span><br><span class="line"> <span class="keyword">input</span> <span class="keyword">signed</span> [<span class="number">15</span>:<span class="number">0</span>] b, <span class="comment">// 输入 b(乘数 )</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">signed</span> [<span class="number">39</span>:<span class="number">0</span>] z <span class="comment">//乘积输出z</span></span><br><span class="line">);</span><br><span class="line"><span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">15</span>:<span class="number">0</span>] b_reg;</span><br><span class="line"><span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">24</span>:<span class="number">0</span>] a_reg;</span><br><span class="line"><span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">40</span>:<span class="number">0</span>] z_reg;</span><br><span class="line"><span class="keyword">reg</span> <span class="keyword">signed</span> [<span class="number">40</span>:<span class="number">0</span>] temp;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">assign</span> a_reg = {a[<span class="number">23</span>], a};</span><br><span class="line"><span class="keyword">assign</span> z = z_reg[<span class="number">40</span>:<span class="number">0</span>];</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">integer</span> i;</span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rstn)<span class="keyword">begin</span> <span class="comment">//组合逻辑</span></span><br><span class="line"> <span class="keyword">if</span>(!rstn) </span><br><span class="line"> z_reg = <span class="number">41'b0</span>;</span><br><span class="line"> b_reg = <span class="number">16'b0</span>;</span><br><span class="line"> temp = <span class="number">41'b0</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">begin</span></span><br><span class="line"> temp = {a_reg, <span class="number">16'b0</span>};</span><br><span class="line"> b_reg = b;</span><br><span class="line"> z_reg = <span class="number">41'b0</span>;</span><br><span class="line"> <span class="keyword">if</span>(b[<span class="number">0</span>])</span><br><span class="line"> z_reg = z_reg - temp;</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> z_reg = z_reg;</span><br><span class="line"> <span class="comment">/* </span></span><br><span class="line"><span class="comment"> 因为被乘的旋转因子是16位宽的,所以使用booth算法需要执行16次,这里因为</span></span><br><span class="line"><span class="comment"> 每次的判断条件和操作都是一样的,所以使用for循环将相同电路复制16次 </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>; i < <span class="number">16</span>; i = i + <span class="number">1</span>) </span><br><span class="line"> <span class="keyword">begin</span> </span><br><span class="line"> z_reg = {z_reg[<span class="number">40</span>], z_reg[<span class="number">40</span>:<span class="number">1</span>]};</span><br><span class="line"> <span class="keyword">if</span>(b_reg[<span class="number">1</span>:<span class="number">0</span>] == <span class="number">2'b10</span>)</span><br><span class="line"> z_reg = z_reg - temp; </span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(b_reg[<span class="number">1</span>:<span class="number">0</span>] == <span class="number">2'b01</span>)</span><br><span class="line"> z_reg = z_reg + temp;</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> z_reg = z_reg;</span><br><span class="line"> b_reg = {b_reg[<span class="number">15</span>], b_reg[<span class="number">15</span>:<span class="number">1</span>]};</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span> </span><br><span class="line"><span class="keyword">endmodule</span></span><br></pre></td></tr></tbody></table></figure>
<p> 这里的for循环只是用来通过综合器将其中的电路重复复制16次,经过仿真,与将for循环展开的结果是一样的。</p>
<h2 id="顶层模块设计">顶层模块设计</h2>
<p> 此次设计的128点fft输入和输出均为24位,由于采用了阵列架构的设计,所以128点fft共需要448组蝶形运算,如果手动设计,耗时耗力,且出错不容易排查。最终采用C语言输出每级的蝶形运算单元,通过算法语言将每级每个数据和下级的输入数据对应关系进行映射。部分生成代码如下:</p>
<p><img src="/2021/11/04/DFT-FFT/image-20211227121243001.png"></p>
<center style="color:#4F4F4F">
图8-程序生成结果
</center>
<p> "code_state_1-7.txt"为生成的每级的蝶形单元;"assign.txt"为顶层模块中的相关赋值。"matlab_step128.txt"为matlab验证结果模块。"tb.txt"为测试文件使用。</p>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">15</span>:<span class="number">0</span>] factor_real [<span class="number">63</span>:<span class="number">0</span>];</span><br><span class="line"><span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">15</span>:<span class="number">0</span>] factor_imag [<span class="number">63</span>:<span class="number">0</span>];</span><br><span class="line"><span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] xm_real [<span class="number">7</span>:<span class="number">0</span>][<span class="number">127</span>:<span class="number">0</span>] ;<span class="comment">//[stage][num]</span></span><br><span class="line"><span class="keyword">wire</span> <span class="keyword">signed</span> [<span class="number">23</span>:<span class="number">0</span>] xm_imag [<span class="number">7</span>:<span class="number">0</span>][<span class="number">127</span>:<span class="number">0</span>] ;</span><br><span class="line"><span class="keyword">wire</span> en_connect [<span class="number">7</span>:<span class="number">0</span>][<span class="number">63</span>:<span class="number">0</span>] ;<span class="comment">//64+64+64+64+64+64+64+64</span></span><br></pre></td></tr></tbody></table></figure>
<p><img src="/2021/11/04/DFT-FFT/image-20211227122334433.png"></p>
<p><img src="/2021/11/04/DFT-FFT/image-20211227122654021.png" style="zoom:80%;"></p>
<center style="color:#4F4F4F">
图9-部分生成结果
</center>
<p> 由于代码过长,这里只展示关键部分,总体思路是:将上文中总结的蝶形运算的每级的输入的对应关系转换为代码中的每组数据的输入输出位置。</p>
<h2 id="仿真测试">仿真测试</h2>
<p> 在进行verilog代码仿真前,先将蝶形运算的过程生成matlab代码,使用matlab进行算法思路的初步测试,旋转因子使用浮点数据。</p>
<figure class="highlight matlab"><table><tbody><tr><td class="code"><pre><span class="line"><span class="comment">%%生成旋转因子,和输入数据,以及反序</span></span><br><span class="line">N = <span class="number">128</span>;</span><br><span class="line"><span class="keyword">for</span> r=<span class="number">0</span>:<span class="number">63</span></span><br><span class="line"> Wnr(r+<span class="number">1</span>) = <span class="built_in">cos</span>(<span class="number">2</span>*<span class="built_in">pi</span>*r/N) - <span class="number">1</span><span class="built_in">i</span>*<span class="built_in">sin</span>(<span class="number">2</span>*<span class="built_in">pi</span>*r/N);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">x = [<span class="number">100</span>,<span class="number">97</span>,<span class="number">94</span>,<span class="number">91</span>,<span class="number">88</span>,<span class="number">85</span>,<span class="number">82</span>,...</span><br><span class="line"> <span class="number">79</span>,<span class="number">76</span>,<span class="number">73</span>,<span class="number">70</span>,<span class="number">67</span>,<span class="number">64</span>,<span class="number">61</span>,<span class="number">58</span>,<span class="number">55</span>,<span class="number">52</span>,<span class="number">49</span>,<span class="number">46</span>,<span class="number">43</span>,<span class="number">40</span>,<span class="number">37</span>,<span class="number">34</span>,<span class="number">31</span>,<span class="number">28</span>,<span class="number">25</span>,...</span><br><span class="line"> <span class="number">22</span>,<span class="number">19</span>,<span class="number">16</span>,<span class="number">13</span>,<span class="number">10</span>,<span class="number">7</span>,<span class="number">4</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">5</span>,<span class="number">8</span>,<span class="number">11</span>,<span class="number">14</span>,<span class="number">17</span>,<span class="number">20</span>,<span class="number">23</span>,<span class="number">26</span>,<span class="number">29</span>,<span class="number">32</span>,<span class="number">35</span>,<span class="number">38</span>,<span class="number">41</span>,...</span><br><span class="line"> <span class="number">44</span>,<span class="number">47</span>,<span class="number">50</span>,<span class="number">53</span>,<span class="number">56</span>,<span class="number">59</span>,<span class="number">62</span>,<span class="number">65</span>,<span class="number">68</span>,<span class="number">71</span>,<span class="number">74</span>,<span class="number">77</span>,<span class="number">80</span>,<span class="number">83</span>,<span class="number">86</span>,<span class="number">89</span>,<span class="number">92</span>,<span class="number">95</span>,<span class="number">98</span>,<span class="number">101</span>,...</span><br><span class="line"> <span class="number">104</span>,<span class="number">107</span>,<span class="number">110</span>,<span class="number">113</span>,<span class="number">116</span>,<span class="number">119</span>,<span class="number">122</span>,<span class="number">125</span>,<span class="number">128</span>,<span class="number">131</span>,<span class="number">134</span>,<span class="number">137</span>,<span class="number">140</span>,<span class="number">143</span>,<span class="number">146</span>,<span class="number">149</span>,...</span><br><span class="line"> <span class="number">152</span>,<span class="number">155</span>,<span class="number">158</span>,<span class="number">161</span>,<span class="number">164</span>,<span class="number">167</span>,<span class="number">170</span>,<span class="number">173</span>,<span class="number">176</span>,<span class="number">179</span>,<span class="number">182</span>,<span class="number">185</span>,<span class="number">188</span>,<span class="number">191</span>,<span class="number">194</span>,<span class="number">197</span>,<span class="number">200</span>,... <span class="number">203</span>,<span class="number">206</span>,<span class="number">209</span>,<span class="number">212</span>,<span class="number">215</span>,<span class="number">218</span>,<span class="number">221</span>,<span class="number">224</span>,<span class="number">227</span>,<span class="number">230</span>,<span class="number">233</span>,<span class="number">236</span>,<span class="number">239</span>,<span class="number">242</span>,<span class="number">245</span>,<span class="number">248</span>,<span class="number">251</span>,<span class="number">254</span>,... <span class="number">257</span>,<span class="number">260</span>,<span class="number">263</span>,<span class="number">266</span>,<span class="number">269</span>,<span class="number">272</span>,<span class="number">275</span>,<span class="number">278</span>,<span class="number">281</span>];</span><br><span class="line">v = bitrevorder(a);</span><br><span class="line">v = v+<span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span> a=<span class="number">0</span>:<span class="number">1</span>:<span class="number">127</span></span><br><span class="line"> xm0(a+<span class="number">1</span>) = x(v(a+<span class="number">1</span>));</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></tbody></table></figure>
<p> 使用上面程序生成的matlab_step128.txt中的代码进行运算。</p>
<p><img src="/2021/11/04/DFT-FFT/image-20211227124648254.png"></p>
<p><img src="/2021/11/04/DFT-FFT/image-20211227123859958.png"></p>
<center style="color:#4F4F4F">
图10-matlab_step128生成结果
</center>
<p> 通过代码将每级运算后蝶形单元的数值打印,最后生成输出数据,这样也便于对比fpga每个蝶形单元的输入和输出数据是否对应,便于排错。下图为matlab自带函数与生成的算法代码的结果对比。</p>
<p><img src="/2021/11/04/DFT-FFT/untitled.svg"></p>
<center style="color:#4F4F4F">
图11-matlab自带函数和算法生成的函数对比
</center>
<p> 由于旋转因子使用的是浮点数据,虽然每级运算后都四舍五入进行取整,但结果和自带的函数基本一致。</p>
<p> 之后,在进行Verilog的仿真测试,通过测试文件,将输入和输出数据文件写入txt。再通过matlab进行三种方法的对比。</p>
<p><img src="/2021/11/04/DFT-FFT/untitled1.svg"></p>
<p><img src="/2021/11/04/DFT-FFT/image-20211227130105029.png"></p>
<center style="color:#4F4F4F">
图12-三种算法对比
</center>
<p> 从图中可以看出由于fpga中输入的旋转因子是进行定点扩大的,所以对比matlab中的函数会产生误差,但从图中整体来看,fpga输出的结果还是和matlab中的结果基本吻合。</p>
<h1 id="资源下载">资源下载</h1>
<p><a href="my_fft.zip">点击下载全部代码</a></p>
<link rel="stylesheet" href="/css/spoiler.css" type="text/css"><script src="/js/spoiler.js" type="text/javascript" async></script>]]></content>
<categories>
<category>FPGA</category>
<category>Verilog</category>
<category>傅里叶变换</category>
</categories>
<tags>
<tag>DFT-FFT</tag>
</tags>
</entry>
<entry>
<title>学习记录-2</title>
<url>/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/</url>
<content><![CDATA[<p><strong><em>接上节:学习记录-1</em></strong></p>
<span id="more"></span>
<h1 id="另一种代码编写方法">另一种代码编写方法</h1>
<p> 上节使用了count寄存器作为所投金额的计数,这样减少了状态机的状态情况。本节将代码采用分步考虑,即每投一次货币,状态跳转一次,将所有金额情况全部包含,这样会增加很多种状态情况。</p>
<h2 id="verilog代码如下">Verilog代码如下</h2>
<p> </p><div class="spoiler collapsed">
<div class="spoiler-title">
代码
</div>
<div class="spoiler-content">
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="meta">`<span class="meta-keyword">timescale</span> 1ns / 1ps</span></span><br><span class="line"><span class="comment">//////////////////////////////////////////////////////////////////////////////////</span></span><br><span class="line"><span class="comment">// Company: </span></span><br><span class="line"><span class="comment">// Engineer: </span></span><br><span class="line"><span class="comment">// </span></span><br><span class="line"><span class="comment">// Create Date: 2021/10/26 13:57:10</span></span><br><span class="line"><span class="comment">// Design Name: </span></span><br><span class="line"><span class="comment">// Module Name: shopping_2</span></span><br><span class="line"><span class="comment">// Project Name: </span></span><br><span class="line"><span class="comment">// Target Devices: </span></span><br><span class="line"><span class="comment">// Tool Versions: </span></span><br><span class="line"><span class="comment">// Description: </span></span><br><span class="line"><span class="comment">// </span></span><br><span class="line"><span class="comment">// Dependencies: </span></span><br><span class="line"><span class="comment">// </span></span><br><span class="line"><span class="comment">// Revision:</span></span><br><span class="line"><span class="comment">// Revision 0.01 - File Created</span></span><br><span class="line"><span class="comment">// Additional Comments:</span></span><br><span class="line"><span class="comment">// </span></span><br><span class="line"><span class="comment">//////////////////////////////////////////////////////////////////////////////////</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> shopping_2(</span><br><span class="line"> <span class="keyword">input</span> clk,</span><br><span class="line"> <span class="keyword">input</span> rst_n,</span><br><span class="line"> <span class="keyword">input</span> [<span class="number">2</span>:<span class="number">0</span>] din, <span class="comment">// 投1元,5元</span></span><br><span class="line"> <span class="keyword">input</span> [<span class="number">2</span>:<span class="number">0</span>] choose, <span class="comment">// 货物选择 1:6元,2:9元</span></span><br><span class="line"> <span class="keyword">input</span> confirm, <span class="comment">// 选择后确认货物</span></span><br><span class="line"> <span class="keyword">input</span> reconfirm, <span class="comment">// 确认后可以重新选择</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> dout, <span class="comment">// 出货</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> [<span class="number">5</span>:<span class="number">0</span>] change, <span class="comment">// 找钱</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> empty_6, <span class="comment">// 6元货物空信号</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> empty_9 <span class="comment">// 9元货物空信号</span></span><br><span class="line"> <span class="comment">// output reg [4:0] count // 当前总金额 ,输出到tb文件查看用</span></span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">5</span>:<span class="number">0</span>] curr_state, next_state;</span><br><span class="line"><span class="comment">// reg [4:0] count ; // 当前总金额 </span></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">6</span>:<span class="number">0</span>] goods_6 ; <span class="comment">// 初始63</span></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">6</span>:<span class="number">0</span>] goods_9 ; <span class="comment">// 初始63</span></span><br><span class="line"><span class="comment">// reg [6:0] goods_10 ; // 初始63</span></span><br><span class="line"><span class="comment">// reg [6:0] goods_16 ; // 初始63</span></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">7</span>:<span class="number">0</span>] time_cnt ; <span class="comment">// 计时60s</span></span><br><span class="line"><span class="keyword">reg</span> time_out ; <span class="comment">// 时间计数完信号</span></span><br><span class="line"><span class="keyword">reg</span> time_begin ; <span class="comment">// 时间开始计数信号</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -----------------------货物全局初始化-------------------------</span></span><br><span class="line"><span class="keyword">parameter</span> INIT = <span class="number">33</span> ; <span class="comment">// 货物不够就初始化装货</span></span><br><span class="line"><span class="keyword">parameter</span> IDLE = <span class="number">44</span> ; <span class="comment">// 选择货物</span></span><br><span class="line"><span class="comment">// ------------------------------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -----------------------6元货物状态:-------------------------</span></span><br><span class="line"><span class="keyword">parameter</span> S6_0 = <span class="number">1</span> ; <span class="comment">// 累计支付0元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_1 = <span class="number">2</span> ; <span class="comment">// 累计支付1元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_2 = <span class="number">3</span> ; <span class="comment">// 累计支付2元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_3 = <span class="number">4</span> ; <span class="comment">// 累计支付3元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_4 = <span class="number">5</span> ; <span class="comment">// 累计支付4元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_5 = <span class="number">6</span> ; <span class="comment">// 累计支付5元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_6 = <span class="number">7</span> ; <span class="comment">// 累计支付6元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_7 = <span class="number">8</span> ; <span class="comment">// 累计支付7元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_8 = <span class="number">9</span> ; <span class="comment">// 累计支付8元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_9 = <span class="number">10</span> ; <span class="comment">// 累计支付9元</span></span><br><span class="line"><span class="keyword">parameter</span> S6_10 = <span class="number">11</span> ; <span class="comment">// 累计支付10元</span></span><br><span class="line"><span class="comment">// ------------------------------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -----------------------9元货物状态:-------------------------</span></span><br><span class="line"><span class="keyword">parameter</span> S9_0 = <span class="number">12</span> ; <span class="comment">// 累计支付0元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_1 = <span class="number">13</span> ; <span class="comment">// 累计支付1元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_2 = <span class="number">14</span> ; <span class="comment">// 累计支付2元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_3 = <span class="number">15</span> ; <span class="comment">// 累计支付3元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_4 = <span class="number">16</span> ; <span class="comment">// 累计支付4元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_5 = <span class="number">17</span> ; <span class="comment">// 累计支付5元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_6 = <span class="number">18</span> ; <span class="comment">// 累计支付6元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_7 = <span class="number">19</span> ; <span class="comment">// 累计支付7元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_8 = <span class="number">20</span> ; <span class="comment">// 累计支付8元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_9 = <span class="number">21</span> ; <span class="comment">// 累计支付9元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_10 = <span class="number">22</span> ; <span class="comment">// 累计支付10元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_11 = <span class="number">23</span> ; <span class="comment">// 累计支付11元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_12 = <span class="number">24</span> ; <span class="comment">// 累计支付12元</span></span><br><span class="line"><span class="keyword">parameter</span> S9_13 = <span class="number">25</span> ; <span class="comment">// 累计支付13元</span></span><br><span class="line"><span class="comment">// ------------------------------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @功能: 第一个always块,描述状态转移</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> curr_state <= INIT;</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> curr_state <= next_state;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @功能: 计时60s</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span> </span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">8'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(next_state == IDLE)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">8'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_begin == <span class="number">1'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_cnt >= <span class="number">8'd60</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">1'd1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= time_cnt + <span class="number">8'd1</span>;</span><br><span class="line"> time_out <= <span class="number">1'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">8'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @功能: 描述状态转移条件。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">always</span> @(din, choose, time_out, empty_6, reconfirm, empty_9) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">case</span> (curr_state)</span><br><span class="line"> INIT:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = <span class="number">7'd10</span>;</span><br><span class="line"> goods_9 = <span class="number">7'd10</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> IDLE:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(empty_6 == <span class="number">1'b1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = <span class="number">7'd10</span>;</span><br><span class="line"> next_state = INIT;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(empty_9 == <span class="number">1'b1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = <span class="number">7'd10</span>;</span><br><span class="line"> next_state = INIT;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(choose == <span class="number">3'd1</span>) <span class="comment">// 选择6元货物</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b1</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_0;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(choose == <span class="number">3'd2</span>) <span class="comment">// 选择9元货物</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b1</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_0;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="comment">// 没有选择信号</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_0:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_1;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_5;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_0;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> S6_1:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_2;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_6;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_1;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_2:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_3;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_7;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_2;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_3:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_4;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_8;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_3;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_4:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_5;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_9;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_4;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_5:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_6;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_10;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_5;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_6:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_7:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_8:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_9:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_10:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="comment">// ------------9元货物------------------------</span></span><br><span class="line"> S9_0:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_1;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_5;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_0;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_1:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_2;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_6;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_1;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_2:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_3;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_7;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_2;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_3:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_4;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_8;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_3;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_4:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_5;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_9;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_4;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_5:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_6;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_10;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_5;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_6:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_7;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_11;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_6;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_7:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_8;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_12;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_7;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_8:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(din == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_9;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(din == <span class="number">3'd5</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_13;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_8;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_9:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_10:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_11:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_12:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_13:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">default</span>: ;</span><br><span class="line"> <span class="keyword">endcase</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @功能: 描述每种状态的输出。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= <span class="number">6'd0</span>;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(goods_6 <= <span class="number">7'd0</span>) <span class="comment">// 6元货物是否足够</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b1</span>;</span><br><span class="line"> change <= <span class="number">6'd0</span>;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(goods_9 <= <span class="number">7'd0</span>) <span class="comment">// 6元货物是否足够</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b1</span>;</span><br><span class="line"> change <= <span class="number">6'd0</span>;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(time_out == <span class="number">1'b1</span>) <span class="comment">// 超时后将所投钱币原数返还。</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">if</span>(curr_state <= <span class="number">6'd11</span>)</span><br><span class="line"> change <= curr_state - <span class="number">6'd1</span>;</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> change <= curr_state - <span class="number">6'd12</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">case</span> (curr_state)</span><br><span class="line"> S6_6:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd7</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_7:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd7</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_8:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd7</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_9:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd7</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_10:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd7</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_9:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd21</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_10:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd21</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_11:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd21</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_12:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd21</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_13:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= curr_state - <span class="number">6'd21</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= <span class="number">6'd0</span>;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">endcase</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">endmodule</span></span><br></pre></td></tr></tbody></table></figure>
</div>
</div><p></p>
<h2 id="本代码的模块内容细节">本代码的模块内容细节</h2>
<h3 id="entity-shopping_2">Entity: shopping_2</h3>
<h4 id="diagram">Diagram</h4>
<p><img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/shopping_2.svg" alt="shopping_2"> #### Description ##### Generics</p>
<table>
<thead>
<tr class="header">
<th>Generic name</th>
<th>Type</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>INIT</td>
<td>parameter</td>
<td>33</td>
<td>初始化状态,将货物全部装满</td>
</tr>
<tr class="even">
<td>IDLE</td>
<td>parameter</td>
<td>44</td>
<td>空闲状态等待投币</td>
</tr>
<tr class="odd">
<td>S6_0</td>
<td>parameter</td>
<td>1</td>
<td>6元货物累计投入0元</td>
</tr>
<tr class="even">
<td>S6_1</td>
<td>parameter</td>
<td>2</td>
<td>6元货物累计投入1元</td>
</tr>
<tr class="odd">
<td>S6_2</td>
<td>parameter</td>
<td>3</td>
<td>6元货物累计投入2元</td>
</tr>
<tr class="even">
<td>S6_3</td>
<td>parameter</td>
<td>4</td>
<td>6元货物累计投入3元</td>
</tr>
<tr class="odd">
<td>S6_4</td>
<td>parameter</td>
<td>5</td>
<td>6元货物累计投入4元</td>
</tr>
<tr class="even">
<td>S6_5</td>
<td>parameter</td>
<td>6</td>
<td>6元货物累计投入5元</td>
</tr>
<tr class="odd">
<td>S6_6</td>
<td>parameter</td>
<td>7</td>
<td>6元货物累计投入6元</td>
</tr>
<tr class="even">
<td>S6_7</td>
<td>parameter</td>
<td>8</td>
<td>6元货物累计投入7元</td>
</tr>
<tr class="odd">
<td>S6_8</td>
<td>parameter</td>
<td>9</td>
<td>6元货物累计投入8元</td>
</tr>
<tr class="even">
<td>S6_9</td>
<td>parameter</td>
<td>10</td>
<td>6元货物累计投入9元</td>
</tr>
<tr class="odd">
<td>S6_10</td>
<td>parameter</td>
<td>11</td>
<td>6元货物累计投入10元</td>
</tr>
<tr class="even">
<td>S9_0</td>
<td>parameter</td>
<td>12</td>
<td>9元货物累计投入0元</td>
</tr>
<tr class="odd">
<td>S9_1</td>
<td>parameter</td>
<td>13</td>
<td>9元货物累计投入1元</td>
</tr>
<tr class="even">
<td>S9_2</td>
<td>parameter</td>
<td>14</td>
<td>9元货物累计投入2元</td>
</tr>
<tr class="odd">
<td>S9_3</td>
<td>parameter</td>
<td>15</td>
<td>9元货物累计投入3元</td>
</tr>
<tr class="even">
<td>S9_4</td>
<td>parameter</td>
<td>16</td>
<td>9元货物累计投入4元</td>
</tr>
<tr class="odd">
<td>S9_5</td>
<td>parameter</td>
<td>17</td>
<td>9元货物累计投入5元</td>
</tr>
<tr class="even">
<td>S9_6</td>
<td>parameter</td>
<td>18</td>
<td>9元货物累计投入6元</td>
</tr>
<tr class="odd">
<td>S9_7</td>
<td>parameter</td>
<td>19</td>
<td>9元货物累计投入7元</td>
</tr>
<tr class="even">
<td>S9_8</td>
<td>parameter</td>
<td>20</td>
<td>9元货物累计投入8元</td>
</tr>
<tr class="odd">
<td>S9_9</td>
<td>parameter</td>
<td>21</td>
<td>9元货物累计投入9元</td>
</tr>
<tr class="even">
<td>S9_10</td>
<td>parameter</td>
<td>22</td>
<td>9元货物累计投入10元</td>
</tr>
<tr class="odd">
<td>S9_11</td>
<td>parameter</td>
<td>23</td>
<td>9元货物累计投入11元</td>
</tr>
<tr class="even">
<td>S9_12</td>
<td>parameter</td>
<td>24</td>
<td>9元货物累计投入12元</td>
</tr>
<tr class="odd">
<td>S9_13</td>
<td>parameter</td>
<td>25</td>
<td>9元货物累计投入13元</td>
</tr>
</tbody>
</table>
<h5 id="ports">Ports</h5>
<table>
<thead>
<tr class="header">
<th>Port name</th>
<th>Direction</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>clk</td>
<td>input</td>
<td></td>
<td>时钟</td>
</tr>
<tr class="even">
<td>rst_n</td>
<td>input</td>
<td></td>
<td>复位</td>
</tr>
<tr class="odd">
<td>din</td>
<td>input</td>
<td>[2:0]</td>
<td>投入货币1元或5元</td>
</tr>
<tr class="even">
<td>choose</td>
<td>input</td>
<td>[2:0]</td>
<td>选择货物:3'd1和3'd2为6元和9元货物</td>
</tr>
<tr class="odd">
<td>confirm</td>
<td>input</td>
<td></td>
<td>确认信号</td>
</tr>
<tr class="even">
<td>reconfirm</td>
<td>input</td>
<td></td>
<td>本例中并没有使用</td>
</tr>
<tr class="odd">
<td>dout</td>
<td>output</td>
<td></td>
<td>货物输出信号1有效</td>
</tr>
<tr class="even">
<td>change</td>
<td>output</td>
<td>[5:0]</td>
<td>找零</td>
</tr>
<tr class="odd">
<td>empty_6</td>
<td>output</td>
<td></td>
<td>6元货物空信号</td>
</tr>
<tr class="even">
<td>empty_9</td>
<td>output</td>
<td></td>
<td>9元货物空信号</td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h5 id="signals-or-reg">Signals or reg</h5>
<table>
<thead>
<tr class="header">
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>curr_state</td>
<td>reg [5:0]</td>
<td>当前状态</td>
</tr>
<tr class="even">
<td>next_state</td>
<td>reg [5:0]</td>
<td>下一状态</td>
</tr>
<tr class="odd">
<td>goods_6</td>
<td>reg [6:0]</td>
<td>6元货物数量</td>
</tr>
<tr class="even">
<td>goods_9</td>
<td>reg [6:0]</td>
<td>9元货物数量</td>
</tr>
<tr class="odd">
<td>time_cnt</td>
<td>reg [7:0]</td>
<td>时间计数器</td>
</tr>
<tr class="even">
<td>time_out</td>
<td>reg</td>
<td>超时信号</td>
</tr>
<tr class="odd">
<td>time_begin</td>
<td>reg</td>
<td>开始计时信号</td>
</tr>
</tbody>
</table>
<h5 id="processes">Processes</h5>
<p>时序逻辑描述状态转移: ( @(posedge clk or negedge rst_n) )</p>
<p>计时60s模块: ( @(posedge clk or negedge rst_n) )</p>
<p>组合逻辑描述状态转移: ( @(din, choose, time_out, empty_6, reconfirm, empty_9) )</p>
<p>时序逻辑输出结果: ( @(posedge clk or negedge rst_n) )</p>
<h5 id="state-machines">State machines</h5>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/stm_shopping_2_00.svg" alt="stm_shopping_2_00"><figcaption aria-hidden="true">stm_shopping_2_00</figcaption>
</figure>
<h2 id="仿真测试">仿真测试</h2>
<h3 id="testbench代码">testbench代码</h3>
<p> </p><div class="spoiler collapsed">
<div class="spoiler-title">
testbench代码
</div>
<div class="spoiler-content">
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="comment">//~ `New testbench</span></span><br><span class="line"><span class="meta">`<span class="meta-keyword">timescale</span> 1ns / 1ps</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> tb_shopping_2;</span><br><span class="line"></span><br><span class="line"><span class="comment">// shopping_2 Parameters</span></span><br><span class="line"><span class="keyword">parameter</span> PERIOD = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">parameter</span> INIT = <span class="number">33</span>;</span><br><span class="line"><span class="keyword">parameter</span> IDLE = <span class="number">44</span>;</span><br><span class="line"><span class="keyword">parameter</span> S6_0 = <span class="number">1</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_1 = <span class="number">2</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_2 = <span class="number">3</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_3 = <span class="number">4</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_4 = <span class="number">5</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_5 = <span class="number">6</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_6 = <span class="number">7</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_7 = <span class="number">8</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_8 = <span class="number">9</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_9 = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">parameter</span> S6_10 = <span class="number">11</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_0 = <span class="number">12</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_1 = <span class="number">13</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_2 = <span class="number">14</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_3 = <span class="number">15</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_4 = <span class="number">16</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_5 = <span class="number">17</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_6 = <span class="number">18</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_7 = <span class="number">19</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_8 = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_9 = <span class="number">21</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_10 = <span class="number">22</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_11 = <span class="number">23</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_12 = <span class="number">24</span>;</span><br><span class="line"><span class="keyword">parameter</span> S9_13 = <span class="number">25</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// shopping_2 Inputs</span></span><br><span class="line"><span class="keyword">reg</span> clk = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> rst_n = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> [<span class="number">2</span>:<span class="number">0</span>] din = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> [<span class="number">2</span>:<span class="number">0</span>] choose = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> confirm = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> reconfirm = <span class="number">0</span> ;</span><br><span class="line"></span><br><span class="line"><span class="comment">// shopping_2 Outputs</span></span><br><span class="line"><span class="keyword">wire</span> dout ;</span><br><span class="line"><span class="keyword">wire</span> [<span class="number">5</span>:<span class="number">0</span>] change ;</span><br><span class="line"><span class="keyword">wire</span> empty_6 ;</span><br><span class="line"><span class="keyword">wire</span> empty_9 ;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">initial</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">forever</span> <span class="variable">#(PERIOD/2)</span> clk=~clk;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">initial</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> rst_n = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line">shopping_2 #(</span><br><span class="line"> <span class="variable">.INIT</span> ( INIT ),</span><br><span class="line"> <span class="variable">.IDLE</span> ( IDLE ),</span><br><span class="line"> <span class="variable">.S6_0</span> ( S6_0 ),</span><br><span class="line"> <span class="variable">.S6_1</span> ( S6_1 ),</span><br><span class="line"> <span class="variable">.S6_2</span> ( S6_2 ),</span><br><span class="line"> <span class="variable">.S6_3</span> ( S6_3 ),</span><br><span class="line"> <span class="variable">.S6_4</span> ( S6_4 ),</span><br><span class="line"> <span class="variable">.S6_5</span> ( S6_5 ),</span><br><span class="line"> <span class="variable">.S6_6</span> ( S6_6 ),</span><br><span class="line"> <span class="variable">.S6_7</span> ( S6_7 ),</span><br><span class="line"> <span class="variable">.S6_8</span> ( S6_8 ),</span><br><span class="line"> <span class="variable">.S6_9</span> ( S6_9 ),</span><br><span class="line"> <span class="variable">.S6_10</span> ( S6_10 ),</span><br><span class="line"> <span class="variable">.S9_0</span> ( S9_0 ),</span><br><span class="line"> <span class="variable">.S9_1</span> ( S9_1 ),</span><br><span class="line"> <span class="variable">.S9_2</span> ( S9_2 ),</span><br><span class="line"> <span class="variable">.S9_3</span> ( S9_3 ),</span><br><span class="line"> <span class="variable">.S9_4</span> ( S9_4 ),</span><br><span class="line"> <span class="variable">.S9_5</span> ( S9_5 ),</span><br><span class="line"> <span class="variable">.S9_6</span> ( S9_6 ),</span><br><span class="line"> <span class="variable">.S9_7</span> ( S9_7 ),</span><br><span class="line"> <span class="variable">.S9_8</span> ( S9_8 ),</span><br><span class="line"> <span class="variable">.S9_9</span> ( S9_9 ),</span><br><span class="line"> <span class="variable">.S9_10</span> ( S9_10 ),</span><br><span class="line"> <span class="variable">.S9_11</span> ( S9_11 ),</span><br><span class="line"> <span class="variable">.S9_12</span> ( S9_12 ),</span><br><span class="line"> <span class="variable">.S9_13</span> ( S9_13 ))</span><br><span class="line"> u_shopping_2 (</span><br><span class="line"> <span class="variable">.clk</span> ( clk ),</span><br><span class="line"> <span class="variable">.rst_n</span> ( rst_n ),</span><br><span class="line"> <span class="variable">.din</span> ( din [<span class="number">2</span>:<span class="number">0</span>] ),</span><br><span class="line"> <span class="variable">.choose</span> ( choose [<span class="number">2</span>:<span class="number">0</span>] ),</span><br><span class="line"> <span class="variable">.confirm</span> ( confirm ),</span><br><span class="line"> <span class="variable">.reconfirm</span> ( reconfirm ),</span><br><span class="line"></span><br><span class="line"> <span class="variable">.dout</span> ( dout ),</span><br><span class="line"> <span class="variable">.change</span> ( change [<span class="number">5</span>:<span class="number">0</span>] ),</span><br><span class="line"> <span class="variable">.empty_6</span> ( empty_6 ),</span><br><span class="line"> <span class="variable">.empty_9</span> ( empty_9 )</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">initial</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> rst_n = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*3)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> reconfirm = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> reconfirm = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD*4)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD*10)</span> din = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*4)</span> choose = <span class="number">2</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*4)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> choose = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> choose = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">5</span>;</span><br><span class="line"> <span class="variable">#(PERIOD)</span> din = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">endmodule</span></span><br></pre></td></tr></tbody></table></figure>
</div>
</div><p></p>
<h3 id="仿真结果vivado">仿真结果(vivado)</h3>
<p> 本代码未进行遍历仿真,但把能想到的情况都进行了测试,可以满足超时返回;投币出货;货物存量记录;找钱数目计算等。下面是部分仿真测试波形。</p>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/仿真1.png" alt="仿真1"><figcaption aria-hidden="true">仿真1</figcaption>
</figure>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/仿真2.png" alt="仿真2"><figcaption aria-hidden="true">仿真2</figcaption>
</figure>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/仿真3.png" alt="仿真3"><figcaption aria-hidden="true">仿真3</figcaption>
</figure>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/仿真4.png" alt="仿真4"><figcaption aria-hidden="true">仿真4</figcaption>
</figure>
<h1 id="两种方法的对比">两种方法的对比</h1>
<h2 id="第一种方法的模块细节">第一种方法的模块细节</h2>
<h3 id="entity-shopping_1">Entity: shopping_1</h3>
<h4 id="diagram">Diagram</h4>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/shooping_1.svg" alt="shooping_1"><figcaption aria-hidden="true">shooping_1</figcaption>
</figure>
<h4 id="description">Description</h4>
<h5 id="generics">Generics</h5>
<table>
<thead>
<tr class="header">
<th>Generic name</th>
<th>Type</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>INIT</td>
<td>parameter</td>
<td>11</td>
<td>初始化状态同上</td>
</tr>
<tr class="even">
<td>IDLE</td>
<td>parameter</td>
<td>22</td>
<td>空闲状态同上</td>
</tr>
<tr class="odd">
<td>S6_0</td>
<td>parameter</td>
<td>1</td>
<td>6元货物付款</td>
</tr>
<tr class="even">
<td>S6_1</td>
<td>parameter</td>
<td>2</td>
<td>6元货物出货找零</td>
</tr>
<tr class="odd">
<td>S9_0</td>
<td>parameter</td>
<td>3</td>
<td>9元货物付款</td>
</tr>
<tr class="even">
<td>S9_1</td>
<td>parameter</td>
<td>4</td>
<td>9元货物出货找零</td>
</tr>
</tbody>
</table>
<h5 id="ports描述同上">Ports(描述同上)</h5>
<table>
<thead>
<tr class="header">
<th>Port name</th>
<th>Direction</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>clk</td>
<td>input</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>rst_n</td>
<td>input</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>din</td>
<td>input</td>
<td>[2:0]</td>
<td></td>
</tr>
<tr class="even">
<td>choose</td>
<td>input</td>
<td>[2:0]</td>
<td></td>
</tr>
<tr class="odd">
<td>confirm</td>
<td>input</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>reconfirm</td>
<td>input</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>dout</td>
<td>output</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>change</td>
<td>output</td>
<td>[4:0]</td>
<td></td>
</tr>
<tr class="odd">
<td>empty_6</td>
<td>output</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>empty_9</td>
<td>output</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h5 id="signals描述同上">Signals(描述同上)</h5>
<table>
<thead>
<tr class="header">
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>curr_state</td>
<td>reg [5:0]</td>
<td></td>
</tr>
<tr class="even">
<td>next_state</td>
<td>reg [5:0]</td>
<td></td>
</tr>
<tr class="odd">
<td>count</td>
<td>reg [4:0]</td>
<td></td>
</tr>
<tr class="even">
<td>goods_6</td>
<td>reg [6:0]</td>
<td></td>
</tr>
<tr class="odd">
<td>goods_9</td>
<td>reg [6:0]</td>
<td></td>
</tr>
<tr class="even">
<td>time_cnt</td>
<td>reg [7:0]</td>
<td></td>
</tr>
<tr class="odd">
<td>time_out</td>
<td>reg</td>
<td></td>
</tr>
<tr class="even">
<td>time_begin</td>
<td>reg</td>
<td></td>
</tr>
<tr class="odd">
<td>temp</td>
<td>reg [4:0]</td>
<td></td>
</tr>
</tbody>
</table>
<h5 id="processes">Processes</h5>
<ul>
<li>描述状态转移: ( @(posedge clk or negedge rst_n) )</li>
<li>计时60s模块: ( @(posedge clk or negedge rst_n) )</li>
<li>描述状态转移: ( @(*) )</li>
<li>时序逻辑状态输出: ( @(posedge clk or negedge rst_n) )</li>
</ul>
<h5 id="state-machines">State machines</h5>
<figure>
<img src="/2021/10/27/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-2/stm_shopping_1_00.svg" alt="stm_shopping_1_00"><figcaption aria-hidden="true">stm_shopping_1_00</figcaption>
</figure>
<h2 id="对比">对比</h2>
<p> 第一种状态机由于使用count寄存器对所投钱币进行计数,并将其引用到找零计算中,减少了很多种状态机的跳转情况,较为简洁。</p>
<p> 第二种状态机没有使用寄存器对所投入的钱进行计算,本例是通过状态参数的值和金额对应的关系进行最后找零的计算。将所有金额情况全部写入状态机。</p>
<link rel="stylesheet" href="/css/spoiler.css" type="text/css"><script src="/js/spoiler.js" type="text/javascript" async></script>]]></content>
<categories>
<category>FPGA</category>
<category>Verilog</category>
</categories>
<tags>
<tag>状态机</tag>
</tags>
</entry>
<entry>
<title>学习记录-1</title>
<url>/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/</url>
<content><![CDATA[<p><strong><em>状态机在FPGA设计中具有十分重要的地位,可以实现类似单片机一样的按一定流程“执行”,最后用一个例程来说明。。</em></strong></p>
<span id="more"></span>
<h1 id="状态机的定义">状态机的定义</h1>
<p> <strong>状态机</strong>就是将一个复杂的问题分为很多个步骤,这一步做好了才能去到下一步。比如说实现一个i2c协议发送单字节数据过程,第一步是发送地址;第二步是等待应答,应答成功后进入第三部发送寄存器地址,失败则回到空闲态,然后再次等待发送信号;第四步也是等待应答,应带成功进入第五步发送一个字节数据,失败则返回空闲态,然后等待发送信号,从头开始;第六步等待应答,应答成功则发送stop信号,然后回到空闲态,等下一个发送信号,失败则回到空闲态等发送信号。当然,可以加入发送失败标志判断是否需要重新发送。</p>
<h1 id="moore和mealy状态机">Moore和mealy状态机</h1>
<p> 结构图如下:</p>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/两种状态机.svg" alt="两种状态机"><figcaption aria-hidden="true">两种状态机</figcaption>
</figure>
<table>
<colgroup>
<col style="width: 26%">
<col style="width: 73%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Moore状态机</th>
<th style="text-align: left;">mealy状态机</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"> 输出在时钟边沿变化(总是在一个周期后)。在Mealy机器中,输入更改可能会在逻辑完成后立即导致输出更改, 当两台机器互连时出现大问题 ,可能会发生异步反馈。</td>
<td style="text-align: left;"> 在相同的周期内反应 不需要等待时钟。在Moore机器中,可能需要更多逻辑来将状态解码为输出在时钟边沿之后更多的门延迟。并非所有时序电路都可以使用Mealy模型实现。一些时序电路只能作为摩尔机器实现。</td>
</tr>
</tbody>
</table>
<p> 一开始时对always@(<em>)中的赋值产生疑惑,经过网上查阅后总结组合逻辑用”=“,时序逻辑用“<=”,比较有电路思维的搭配是=和always@ </em>(电平敏感)搭配,<=和always@ (clk)。</p>
<p> 自己试验后发现,vivado综合出来的结果两种都是一样的,软件会自动优化,不同仿真器综合的结果可能会不同。本文在组合逻辑中全部选用“=”。</p>
<h1 id="状态机的描述方法verilog">状态机的描述方法(Verilog)</h1>
<table>
<colgroup>
<col style="width: 9%">
<col style="width: 90%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: right;">类型</th>
<th style="text-align: center;">描述方法</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: right;">一段式</td>
<td style="text-align: center;">整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;</td>
</tr>
<tr class="even">
<td style="text-align: right;">二段式</td>
<td style="text-align: center;">用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;</td>
</tr>
<tr class="odd">
<td style="text-align: right;">三段式</td>
<td style="text-align: center;">在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。</td>
</tr>
</tbody>
</table>
<center>
<font color="#dd00dd">二段式状态机的示例如下:</font><br>
</center>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="comment">// 第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器</span></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> curr_state <= INIT;</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> curr_state <= next_state; <span class="comment">// 注意,使用的是非阻塞赋值</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//第二个进程,采用组合逻辑判断状态转移条件,描述状态转移规律以及输出</span></span><br><span class="line"><span class="keyword">always</span> @ (*) <span class="keyword">begin</span> <span class="comment">//电平触发,组合逻辑</span></span><br><span class="line"> <span class="keyword">case</span>(current_state)</span><br><span class="line"> S1: </span><br><span class="line"> <span class="keyword">if</span>(...)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> data_out = ...;</span><br><span class="line"> next_state = S2; <span class="comment">//阻塞赋值</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> data_out = ...;</span><br><span class="line"> next_state = S1; <span class="comment">//阻塞赋值</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> ...:</span><br><span class="line"> <span class="keyword">endcase</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></tbody></table></figure>
<center>
<font color="#dd00dd">三段式状态机的示例如下:</font><br>
</center>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="comment">// 第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器</span></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> curr_state <= INIT;</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> curr_state <= next_state;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//第二个进程,组合逻辑always模块,描述状态转移条件判断</span></span><br><span class="line"><span class="keyword">always</span> @ (*) <span class="keyword">begin</span> <span class="comment">//电平触发,组合逻辑</span></span><br><span class="line"> <span class="keyword">case</span>(current_state)</span><br><span class="line"> S1: </span><br><span class="line"> <span class="keyword">if</span>(...)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> ...; <span class="comment">//一些条件的判断</span></span><br><span class="line"> next_state = S2; <span class="comment">//阻塞赋值</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> ...; <span class="comment">//一些条件的判断</span></span><br><span class="line"> next_state = S1; <span class="comment">//阻塞赋值</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> ...:</span><br><span class="line"> <span class="keyword">endcase</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> ...; <span class="comment">//初始化</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">case</span>(next_state)</span><br><span class="line"> S1:</span><br><span class="line"> out1 <= <span class="number">1'b1</span>; <span class="comment">//注意是非阻塞逻辑</span></span><br><span class="line"> S2:</span><br><span class="line"> out2 <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">default</span>:...;</span><br><span class="line"> <span class="keyword">endcase</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></tbody></table></figure>
<center>
<font color="#dd00dd">两段式有限状态机与三段式有限状态机的区别</font><br>
</center>
<p> <font color="#dd0000">FSM将时序部分(状态转移部分)和组合部分(判断状态转移条件和产生输出)分开,写为两个always语句,即为两段式有限状态机。将组合部分中的判断状态转移条件和产生输入再分开写,则为三段式有限状态机。<strong>二段式在组合逻辑特别复杂时适用,但要注意需在后面加一个触发器以消除组合逻辑对输出产生的毛刺。三段式没有这个问题,由于第三个always会生成触发器。</strong></font><br></p>
<h1 id="自动售货机示例">自动售货机示例</h1>
<p> 两种货物的情况:为6元的货物,只接受1元和5元的货币,当接受的钱足够时,会吐出货物。当在60个时钟周期内没投够6元时,自动回到初始状态,重新选择货物。货物每出货一个,总数减1,为0时重新装货,如此循环。9元货物同理。</p>
<h2 id="状态转移图">状态转移图</h2>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/状态机.drawio.svg" alt="状态转移图"><figcaption aria-hidden="true">状态转移图</figcaption>
</figure>
<h2 id="代码实现">代码实现</h2>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="meta">`<span class="meta-keyword">timescale</span> 1ns / 1ps</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//////////////////////////////////////////////////////////////////////////////////</span></span><br><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="comment">//////////////////////////////////////////////////////////////////////////////////</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> shopping_1(</span><br><span class="line"> <span class="keyword">input</span> clk,</span><br><span class="line"> <span class="keyword">input</span> rst_n,</span><br><span class="line"> <span class="keyword">input</span> [<span class="number">2</span>:<span class="number">0</span>] din, <span class="comment">// 投1元,5元</span></span><br><span class="line"> <span class="keyword">input</span> [<span class="number">2</span>:<span class="number">0</span>] choose, <span class="comment">// 货物选择 1:6元,2:9元</span></span><br><span class="line"> <span class="keyword">input</span> confirm, <span class="comment">// 选择后确认货物</span></span><br><span class="line"> <span class="keyword">input</span> reconfirm, <span class="comment">// 确认后可以重新选择</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> dout, <span class="comment">// 出货</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> [<span class="number">4</span>:<span class="number">0</span>] change, <span class="comment">// 找钱</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> empty_6, <span class="comment">// 6元货物空信号</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> empty_9, <span class="comment">// 9元货物空信号</span></span><br><span class="line"> <span class="keyword">output</span> <span class="keyword">reg</span> [<span class="number">4</span>:<span class="number">0</span>] count <span class="comment">// 当前总金额 ,输出到tb文件查看用</span></span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">5</span>:<span class="number">0</span>] curr_state, next_state;</span><br><span class="line"><span class="comment">// reg [4:0] count ; // 当前总金额 </span></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">6</span>:<span class="number">0</span>] goods_6 ; <span class="comment">// 初始63</span></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">6</span>:<span class="number">0</span>] goods_9 ; <span class="comment">// 初始63</span></span><br><span class="line"><span class="comment">// reg [6:0] goods_10 ; // 初始63</span></span><br><span class="line"><span class="comment">// reg [6:0] goods_16 ; // 初始63</span></span><br><span class="line"><span class="keyword">reg</span> [<span class="number">7</span>:<span class="number">0</span>] time_cnt ; <span class="comment">// 计时60s</span></span><br><span class="line"><span class="keyword">reg</span> time_out ; <span class="comment">// 时间计数完信号</span></span><br><span class="line"><span class="keyword">reg</span> time_begin ; <span class="comment">// 时间开始计数信号</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -----------------------货物全局初始化-------------------------</span></span><br><span class="line"><span class="keyword">parameter</span> INIT = <span class="number">11</span> ; <span class="comment">// 货物不够就初始化装货</span></span><br><span class="line"><span class="keyword">parameter</span> IDLE = <span class="number">22</span> ; <span class="comment">// 选择货物</span></span><br><span class="line"><span class="comment">// ------------------------------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -----------------------6元货物状态:-------------------------</span></span><br><span class="line"><span class="keyword">parameter</span> S6_0 = <span class="number">1</span> ; <span class="comment">// 支付过程</span></span><br><span class="line"><span class="keyword">parameter</span> S6_1 = <span class="number">2</span> ; <span class="comment">// 满足金额出货</span></span><br><span class="line"><span class="comment">// ------------------------------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -----------------------9元货物状态:-------------------------</span></span><br><span class="line"><span class="keyword">parameter</span> S9_0 = <span class="number">3</span> ; <span class="comment">// 支付过程</span></span><br><span class="line"><span class="keyword">parameter</span> S9_1 = <span class="number">4</span> ; <span class="comment">// 满足金额出货</span></span><br><span class="line"><span class="comment">// ------------------------------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> curr_state <= INIT;</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> curr_state <= next_state;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @功能: 计时60s</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span> </span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">8'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(next_state == IDLE)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">8'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_begin == <span class="number">1'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_cnt >= <span class="number">8'd60</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">1'd1</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= time_cnt + <span class="number">8'd1</span>;</span><br><span class="line"> time_out <= <span class="number">1'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_cnt <= <span class="number">8'd0</span>;</span><br><span class="line"> time_out <= <span class="number">8'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @功能: 描述状态转移,和一些信号的产生。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">always</span> @(*) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">case</span> (curr_state)</span><br><span class="line"> INIT:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = <span class="number">7'd10</span>;</span><br><span class="line"> goods_9 = <span class="number">7'd10</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> IDLE:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(empty_6 == <span class="number">1'b1</span> || empty_9 == <span class="number">1'b1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = <span class="number">7'd10</span>;</span><br><span class="line"> goods_9 = <span class="number">7'd10</span>;</span><br><span class="line"> next_state = INIT;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(choose == <span class="number">3'd1</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b1</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_0;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(choose == <span class="number">3'd2</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b1</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = S9_0;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_0:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">0</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (count >= <span class="number">5'd6</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> count = count;</span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> next_state = S6_1;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> count = count + din;</span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S6_0; </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> count = count;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S6_1:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> count = count;</span><br><span class="line"> goods_6 = goods_6 - <span class="number">7'd1</span>;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_0:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (reconfirm == <span class="number">1'b1</span>) <span class="comment">// 是否重新选择</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">0</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> count = <span class="number">5'd0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (time_out == <span class="number">1'b0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span> (count >= <span class="number">5'd9</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> count = count;</span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> next_state = S9_1;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> count = count + din;</span><br><span class="line"> time_begin = time_begin;</span><br><span class="line"> goods_6 = goods_6;</span><br><span class="line"> next_state = S9_0; </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> count = count;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> time_begin = <span class="number">1'b0</span>;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> S9_1:</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> count = count;</span><br><span class="line"> goods_9 = goods_9 - <span class="number">7'd1</span>;</span><br><span class="line"> goods_9 = goods_9;</span><br><span class="line"> next_state = IDLE;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">default</span>: ;</span><br><span class="line"> <span class="keyword">endcase</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">always</span> @(<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n) <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> change <= <span class="number">5'd0</span>;</span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(curr_state == S6_0 && time_out == <span class="number">1'b1</span> && curr_state == S9_0)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> change <= count;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(curr_state == S6_1)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> change <= count - <span class="number">5'd6</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">if</span>(goods_6 <= <span class="number">7'd0</span>)</span><br><span class="line"> empty_6 <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(curr_state == S9_1)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> change <= count - <span class="number">5'd9</span>;</span><br><span class="line"> dout <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">if</span>(goods_9 <= <span class="number">7'd0</span>)</span><br><span class="line"> empty_9 <= <span class="number">1'b1</span>;</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> change <= <span class="number">5'd0</span>;</span><br><span class="line"> dout <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_6 <= <span class="number">1'b0</span>;</span><br><span class="line"> empty_9 <= <span class="number">1'b0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">endmodule</span></span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure>
<p>testbench文件:</p>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="comment">//~ `New testbench </span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">choose 的时序还没有调整</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">`<span class="meta-keyword">timescale</span> 1ns / 1ps</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> tb_shopping_1;</span><br><span class="line"></span><br><span class="line"><span class="comment">// shopping_1 Parameters</span></span><br><span class="line"><span class="keyword">parameter</span> PERIOD = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">parameter</span> INIT = <span class="number">11</span>;</span><br><span class="line"><span class="keyword">parameter</span> IDLE = <span class="number">22</span>;</span><br><span class="line"><span class="keyword">parameter</span> S6_0 = <span class="number">1</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S6_1 = <span class="number">2</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S9_0 = <span class="number">3</span> ;</span><br><span class="line"><span class="keyword">parameter</span> S9_1 = <span class="number">4</span> ;</span><br><span class="line"></span><br><span class="line"><span class="comment">// shopping_1 Inputs</span></span><br><span class="line"><span class="keyword">reg</span> clk = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> rst_n = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> [<span class="number">2</span>:<span class="number">0</span>] din = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> [<span class="number">2</span>:<span class="number">0</span>] choose = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> confirm = <span class="number">0</span> ;</span><br><span class="line"><span class="keyword">reg</span> reconfirm = <span class="number">0</span> ;</span><br><span class="line"></span><br><span class="line"><span class="comment">// shopping_1 Outputs</span></span><br><span class="line"><span class="keyword">wire</span> dout ;</span><br><span class="line"><span class="keyword">wire</span> [<span class="number">4</span>:<span class="number">0</span>] change ;</span><br><span class="line"><span class="keyword">wire</span> empty_6 ;</span><br><span class="line"><span class="keyword">wire</span> empty_9 ;</span><br><span class="line"><span class="keyword">wire</span> [<span class="number">4</span>:<span class="number">0</span>] count ;</span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="keyword">integer</span> file_wr, fp, fp1, data_choose, data, i, j, data_out;</span><br><span class="line"><span class="keyword">reg</span> [<span class="number">10</span>:<span class="number">0</span>] count1;</span><br><span class="line"><span class="keyword">reg</span> [<span class="number">4</span>:<span class="number">0</span>] money;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">initial</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">forever</span> <span class="variable">#(PERIOD/2)</span> clk=~clk;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">initial</span> <span class="keyword">begin</span></span><br><span class="line"> <span class="variable">#(PERIOD*2)</span> rst_n = <span class="number">1</span>;</span><br><span class="line"> file_wr = <span class="built_in">$fopen</span>(<span class="string">"C:/Users/57194/Desktop/1/shopping_1/change.txt"</span>,<span class="string">"w"</span>);</span><br><span class="line"> fp = <span class="built_in">$fopen</span>(<span class="string">"C:/Users/57194/Desktop/1/shopping_1/money.txt"</span>, <span class="string">"r"</span>);</span><br><span class="line"> fp1 = <span class="built_in">$fopen</span>(<span class="string">"C:/Users/57194/Desktop/1/shopping_1/choose.txt"</span>, <span class="string">"r"</span>);</span><br><span class="line"> <span class="variable">#(PERIOD*10000)</span>;</span><br><span class="line"> <span class="built_in">$fclose</span>(fp);</span><br><span class="line"> <span class="built_in">$fclose</span>(fp1);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">always</span> @ (<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n)<span class="keyword">begin</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span>(!rst_n)<span class="keyword">begin</span></span><br><span class="line"> choose <= <span class="number">0</span>;</span><br><span class="line"> data_choose <= <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; fp!=<span class="string">"\0"</span>;i=i+<span class="number">1</span>) <span class="keyword">begin</span></span><br><span class="line"> <span class="variable">#(PERIOD)</span>;</span><br><span class="line"> <span class="built_in">$fscanf</span>(fp, <span class="string">"%d"</span>, data);</span><br><span class="line"> din <= data;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">always</span> @ (<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n)<span class="keyword">begin</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span>(!rst_n)<span class="keyword">begin</span></span><br><span class="line"> choose <= <span class="number">0</span>;</span><br><span class="line"> data_choose <= <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">for</span> (j=<span class="number">0</span>; fp1!=<span class="string">"\0"</span>;j=j+<span class="number">1</span>) <span class="keyword">begin</span></span><br><span class="line"> <span class="variable">#(PERIOD)</span>;</span><br><span class="line"> <span class="built_in">$fscanf</span>(fp1, <span class="string">"%d"</span>, data_choose);</span><br><span class="line"> choose <= data_choose;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">always</span> @ (<span class="keyword">posedge</span> clk <span class="keyword">or</span> <span class="keyword">negedge</span> rst_n)<span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">if</span>(!rst_n)<span class="keyword">begin</span></span><br><span class="line"> data_out<=<span class="number">8'b0</span>;</span><br><span class="line"> count1<=<span class="number">11'b0</span>;</span><br><span class="line"> choose <= <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(count1<<span class="number">11'd1000</span>) <span class="keyword">begin</span></span><br><span class="line"> data_out<=change;</span><br><span class="line"> count1<=count1+<span class="number">1'b1</span>;</span><br><span class="line"> <span class="built_in">$fdisplay</span>(file_wr,<span class="string">"选择 %d 号商品 投入金额:%d 累计支付:%d 找零:%d 是否出货 %d"</span> , choose, din, count, change, dout); </span><br><span class="line"> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="built_in">$fclose</span>(file_wr);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// initial</span></span><br><span class="line"><span class="comment">// begin</span></span><br><span class="line"><span class="comment">// #(PERIOD*2) rst_n = 1;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// #(PERIOD*3) choose = 2;</span></span><br><span class="line"><span class="comment">// #(PERIOD) choose = 0;</span></span><br><span class="line"><span class="comment">// #(PERIOD) reconfirm = 1;</span></span><br><span class="line"><span class="comment">// #(PERIOD) reconfirm = 0;</span></span><br><span class="line"><span class="comment">// #(PERIOD*2) choose = 2;</span></span><br><span class="line"><span class="comment">// #(PERIOD) choose = 0;</span></span><br><span class="line"><span class="comment">// #(PERIOD) din = 1;</span></span><br><span class="line"><span class="comment">// #(PERIOD*4) din = 0;</span></span><br><span class="line"><span class="comment">// #(PERIOD) din = 1;</span></span><br><span class="line"><span class="comment">// #(PERIOD) din = 0;</span></span><br><span class="line"><span class="comment">// #(PERIOD*4) din = 5;</span></span><br><span class="line"><span class="comment">// #(PERIOD) din = 0;</span></span><br><span class="line"><span class="comment">// #(PERIOD*4) din = 5;</span></span><br><span class="line"><span class="comment">// #(PERIOD) din = 0;</span></span><br><span class="line"><span class="comment">// end</span></span><br><span class="line"></span><br><span class="line">shopping_1 #(</span><br><span class="line"> <span class="variable">.INIT</span> ( INIT ),</span><br><span class="line"> <span class="variable">.IDLE</span> ( IDLE ),</span><br><span class="line"> <span class="variable">.S6_0</span> ( S6_0 ),</span><br><span class="line"> <span class="variable">.S6_1</span> ( S6_1 ),</span><br><span class="line"> <span class="variable">.S9_0</span> ( S9_0 ),</span><br><span class="line"> <span class="variable">.S9_1</span> ( S9_1 ))</span><br><span class="line"> u_shopping_1 (</span><br><span class="line"> <span class="variable">.clk</span> ( clk ),</span><br><span class="line"> <span class="variable">.rst_n</span> ( rst_n ),</span><br><span class="line"> <span class="variable">.din</span> ( din [<span class="number">2</span>:<span class="number">0</span>] ),</span><br><span class="line"> <span class="variable">.choose</span> ( choose [<span class="number">2</span>:<span class="number">0</span>] ),</span><br><span class="line"> <span class="variable">.confirm</span> ( confirm ),</span><br><span class="line"> <span class="variable">.reconfirm</span> ( reconfirm ),</span><br><span class="line"></span><br><span class="line"> <span class="variable">.dout</span> ( dout ),</span><br><span class="line"> <span class="variable">.change</span> ( change [<span class="number">4</span>:<span class="number">0</span>] ),</span><br><span class="line"> <span class="variable">.empty_6</span> ( empty_6 ),</span><br><span class="line"> <span class="variable">.empty_9</span> ( empty_9 ),</span><br><span class="line"> <span class="variable">.count</span> ( count [<span class="number">4</span>:<span class="number">0</span>] )</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">endmodule</span></span><br></pre></td></tr></tbody></table></figure>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/仿真.png" alt="仿真结果"><figcaption aria-hidden="true">仿真结果</figcaption>
</figure>
<p><a href="data.zip">点击下载仿真数据</a></p>
<p>仿真中choose信号的到来还未调整,但是功能是正常的。</p>
<h1 id="modelsim-仿真">Modelsim 仿真</h1>
<h2 id="导入文件仿真">导入文件,仿真</h2>
<p> 将文件导入后,全部编译,全部通过后,在开启仿真时选择不启用优化器(<font color="red"> 遇到的问题:仿真时自动启用优化器会报错导致不能进行仿真,晚上查找解决方法后将其关闭</font>)。</p>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/仿真设置.png" alt="仿真设置"><figcaption aria-hidden="true">仿真设置</figcaption>
</figure>
<h2 id="查看波形">查看波形</h2>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/波形.png" alt="波形"><figcaption aria-hidden="true">波形</figcaption>
</figure>
<p> 目前还未对choose信号和din信号先后的到来进行完美的调整,所以会出现choose信号没到来时,din信号先出现。但是这种情况就相当于没选择货物时先投币,这时count计数器并没有触发,相当于并没有对所投的钱进行处理,当choose到来时才会对后续的din进行处理。</p>
<p> 经过之前的手动输入数据,状态机的计时功能,货币累加,出货等状态都可以没有错误的实现,部分测试数据通过matlab随机组合产生,在经过Excel裁剪。matlab代码如下:</p>
<figure class="highlight matlab"><table><tbody><tr><td class="code"><pre><span class="line">clear; clc;</span><br><span class="line"><span class="comment">% money_2 = [1, 2, 5, 1, 2, 5];</span></span><br><span class="line"><span class="comment">% money_3 = [1, 2, 5, 1, 2, 5, 1, 2, 5];</span></span><br><span class="line"><span class="comment">% money_4 = [1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5];</span></span><br><span class="line"><span class="comment">% money_5 = [1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5];</span></span><br><span class="line"><span class="comment">% money_6 = [1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5];</span></span><br><span class="line"><span class="comment">% money_7 = [1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5];</span></span><br><span class="line">paper_money_6 = [<span class="number">1</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">5</span>];</span><br><span class="line"><span class="comment">% random_num = money(randi(numel(money),1,2))</span></span><br><span class="line">random_num = <span class="built_in">nchoosek</span>(paper_money_6,<span class="number">6</span>);</span><br><span class="line">sum = sum(random_num');</span><br><span class="line">sum = sum';</span><br><span class="line">arry = [random_num, sum];</span><br><span class="line">temp = [<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>]</span><br><span class="line">[r, c] = <span class="built_in">size</span>(arry);<span class="comment">%r行c列</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span> = <span class="number">1</span> : r</span><br><span class="line"> <span class="keyword">if</span>(arry(<span class="built_in">i</span>,<span class="number">7</span>)<=<span class="number">10</span>)</span><br><span class="line"> temp = [temp;arry(<span class="built_in">i</span>,:)]</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></tbody></table></figure>
<p> 最后将测试结果输出到txt文件,部分截图如下图所示:</p>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/输出结果txt.png" alt="输出结果txt"><figcaption aria-hidden="true">输出结果txt</figcaption>
</figure>
<h1 id="总结">总结</h1>
<p> 最开始第一次写的状态机是两段式的,中间的变量赋值和状态跳变比较混乱,思路并不是十分清晰。这次将改进为3段式状态机,首先第一个always块用<strong>同步时序</strong>逻辑去描述每次时钟到来时状态的变化;第二个always用<strong>组合逻辑</strong>来进行状态变化的条件判断;第三个always通过<strong>同步时序</strong>逻辑用来描述每种状态的输出。总之最好<strong>状态转移部分是同步时序电路</strong>,而状态的<strong>转移条件的判断是组合逻辑</strong>。</p>
<p> 网上参考了一篇文档(EECS150: Finite State Machines in Verilog ) ,文中主要讲述了设计状态机时应重点注意的事项。文档如下:</p><div class="pdfobject-container" data-target="FSM.pdf" data-height="500px"></div><p></p>
<p> 从文中总结了一些感觉比较重要的注意要点:</p>
<h2 id="wire和reg">wire和reg</h2>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/wire_reg.png" alt="wire_reg"><figcaption aria-hidden="true">wire_reg</figcaption>
</figure>
<p> 两者都可以作为assign的右侧进行赋值,都可以用=和<=。</p>
<h2 id="always中赋值方式">always@(*)中赋值方式</h2>
<figure>
<img src="/2021/10/19/%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E4%B8%80%E4%BA%9B%E7%90%86%E8%A7%A3/always1.png" alt="always1.png"><figcaption aria-hidden="true">always1.png</figcaption>
</figure>
<figure class="highlight verilog"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">always</span> @(A <span class="keyword">or</span> B)<span class="keyword">begin</span></span><br><span class="line"> C = A & B;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 错误写法,敏感列表不完全</span></span><br><span class="line"><span class="keyword">always</span>@ ( A )<span class="keyword">begin</span></span><br><span class="line"> C = A & B ;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">always</span>@ ( B )<span class="keyword">begin</span></span><br><span class="line"> C = A & B ;</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></tbody></table></figure>
<p> 上图中说明always@()中应用“<font color="red"> =</font>”,文中提到一点,就是敏感列表必须全部包含,所以推荐使用<font color="red">always@(*)</font>。示例代码综合出来的模型为下图。</p>