Verilog -- 序列發生器的設計
@(verilog)
1. 題目
產生序列信號11010111至少需要幾級觸發器?
2. 思路1 - 狀態機實現
最容易想到的就是采用狀態機,每個狀態輸出序列中的一位,發送完一組序列后回到開始狀態繼續循環。需要注意的是狀態變量的位寬,由於題目要求采用最少的觸發器,因此至少需要\(log_2(序列長度)\)個狀態,對於本題也就是3個觸發器,輸出邏輯可以采用always(*)純組合邏輯實現。
代碼比較簡單,就不寫了。
3. 思路2 - 移位寄存器實現
序列的問題很多都可以用移位寄存器解決,只是移位寄存器方案可能會消耗較多的寄存器資源。
對於本題,如果規定了模塊只有三個端口:
module seq_gen(
input clk,
input rst_n,
output reg seq );
那么需要在初始化的時候將移位寄存器值初始化為目標序列,或者有一個輸入序列的接口,那就可以在初始化時將序列填入移位寄存器中。代碼如下:
module seq_gen(
input clk,
input rst_n,
output seq );
reg [7:0]out_seq;
always@(posedge clk or negedge rst_n)
if(!rst_n) out_seq <= 8'b11010111;
else out_seq <= {out_seq[6:0],out_seq[7]};
assign seq = out_seq[7];
移位寄存器版本至少需要序列長度個寄存器,也就是8個。
4. 思路3 -- 計數器+組合邏輯
其實最上面的狀態機版本就可以理解為計數器+組合邏輯的方法,因為狀態變量相當於一個計數器。因此狀態機版本的好處在於不需要考慮輸出的組合邏輯怎么搭,直接case無腦就好了。而如果真的要自己手搭輸出的組合邏輯呢?其實也不難,畫個真值表就搞定了:
a0 | a1 | a2 | out |
---|---|---|---|
0 | 0 | 0 | 1 |
0 | 0 | 1 | 1 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 0 | 0 | 0 |
1 | 0 | 1 | 1 |
1 | 1 | 0 | 1 |
1 | 1 | 1 | 1 |
對應的卡諾圖:
a0\a1a2 | 00 | 01 | 10 | 11 |
---|---|---|---|---|
0 | 1 | 1 | 0 | 1 |
1 | 0 | 1 | 1 | 1 |
化簡一下得到:out = \(\overline{\overline{a_0}a_1\overline{a_2}+a_0\overline{a_1}\ \overline{a_2}}\)
因此代碼中只要有一個不斷累加的3位計數器,配合上輸出的組合邏輯表達式即可。
在之前的文章中也提到,如果計數器級數為N, 則環形計數器可以代表的狀態數為N, 扭環形計數器為2N,線性移位反饋寄存器表示的狀態數為2^N-1,所以本題沒辦法使用N=3的上述計數器。