由於篇幅有限,我們用一個3-8解碼器來結束本次對組合邏輯電路的介紹,並且最後我們還給大家準備了一個略微酸爽的任務,確保大家的腦神經都可以得到充分的摩擦。閒話不多說,現在開始。
本次實驗的任務是構建一個3-8解碼器,且將解碼結果通過小腳丫的LED燈顯示。
聽上去並不難,而且我能想像到,一定會有不少同學會立刻開始畫一個8行的真值表,然後通過卡諾圖進行化簡,且根據最終的邏輯表達式畫出門電路圖。這個方法當然沒有錯,不過,如果面對更多位數的系統,比如4-16或者是8-256的解碼器,建一個幾百行的真值表並進行邏輯運算聽上去似乎不那麼科學。
在這裡我們將採用模塊化的思路來完成我們的實驗設計。
在開始進行模塊化設計之前,我們先做一個2-4解碼器,也就是解碼器系列中最底層的基礎模塊。
A1 |
A0 |
Y3 |
Y2 |
Y1 |
Y0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
0 |
0 |
這次的代碼我們採用行為級描述(Behavioral-level)的寫法,直接根據真值表將輸入與輸出的各種組合進行直接關聯。可以看出,行為級的寫法甚至不需要構建門電路,僅通過輸入輸出對應關係即可構建,因此最為抽象,同時也意味著更快的運算速度?。
module decode24
(
input wire [1:0] A, //定義兩位輸入
output reg [3:0] Y //定義輸出的4位解碼結果對應的led
);
always@(A) //always塊語句,a值變化時執行一次過程塊
begin
case(A)
2'b00: Y = 4'b0001; //2-4解碼結果
2'b01: Y = 4'b0010;
2'b10: Y = 4'b0100;
2'b11: Y = 4'b1000;
endcase
end
endmodule
有了最基礎的模塊,如何通過它搭建出3-8解碼器呢?現在,我們在原有的真值表上加上一路使能信號E,再來觀察一下新的真值表。可以發現,當E為低電平時,不論輸入的取值如何,前四位輸出均為0。當E為高電平時,右側仍然為2-4解碼器的輸出結構。
E |
A1 |
A0 |
Y3 |
Y2 |
Y1 |
Y0 |
0 |
X |
X |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
我們可以把表3看作為一個3-8解碼器的真值表,只不過輸入端的最高位由E代替。由於E為低電平時輸出最高的四位均為0,因此確保我們在對後四位輸出(黃色)進行賦值不會影響到前四位的輸出。
A2 |
A1 |
A0 |
Y7 |
Y6 |
Y5 |
Y4 |
Y3 |
Y2 |
Y1 |
Y0 |
E |
A1 |
A0 |
Y3 |
Y2 |
Y1 |
Y0 |
y3 |
y2 |
y1 |
y0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
從表3不難看出,黃框和紅框對應的其實就是一個帶有使能端的2-4解碼器,且使能端E控制著前後半端位數的輸出結果。也就是說,一個3-8解碼器可以由兩個2-4解碼器構成。同理,一個4-16解碼器可以由兩個3-8解碼器構成,以此類推。
帶有使能E的2-4解碼器如下圖所示。實際上就是在之前的代碼上稍做修改,在這裡我們就不詳細寫出來了,給大家自行練習的機會。
接下來,按照之前的分析,我們畫出由兩個2-4解碼器組成的3-8解碼器的結構。
以下是用Verilog寫的一個3-8解碼器,在程序里我們調用了兩次2-4解碼器的子模塊。注意,子模塊的文件需要和decode38文件放在同一個工程目錄下,不然就成了隔壁老王了。
module decode38
(
input wire [2:0] X,
output wire [7:0] D
);
decode24 upper //調用第一個子模塊,命名為upper
(
.a(X[1:0]), //將大模塊的X1,X0與lower的A1,A0匹配
.E(X[2]), //將大模塊的X2與lower的E匹配
.Y(D[7:4]) //將大模塊的D7-D4與lower的Y3-Y0匹配
);
decode24 lower //調用第二個子模塊,命名為lower
(
.a(X[1:0]), //將大模塊的X1,X0與lower的A1,A0匹配
.E(!X[2]), //將大模塊的X2與lower的E匹配
.Y(D[3:0]) //將大模塊的D7-D4與lower的Y3-Y0匹配
);
Endmodule
當你反覆在圖和代碼之間徘徊幾輪,並有了多麼痛的領悟之後,你就可以把自己編譯好的程序下載到小腳丫里,然後通過實驗測試你的代碼了。
練習一下,當我們把輸出D7-D1分別對應為小腳丫上的L7-L1,且輸入X2-X0分別對應至小腳丫的SW3-SW1,請判斷以下的LED狀態。
在倒騰了半天之後,你終於搞定了代碼,並且成功在小腳丫上驗證了你的設計,於是滿懷信心的你 終於可以洗洗睡了 就可以嘗試一下通過模塊化的設計思路去構建4-16甚至更多位的解碼器了。
當然~我知道你們是不會真的再去老老實實寫程序的,所以咱就在這裡提幾個簡單的問題,你們自己做做樣子思考一下就完事兒了。
Q1: 構建4-16解碼器需要幾個3-8解碼器? 答曰:
Q2: 構建4-16解碼器需要幾個2-4解碼器? 答曰:
Q3: 構建5-32解碼器需要幾個2-4解碼器? 答曰:
Q4: 小明家一個4-16的解碼器200塊,小李家2-4解碼器賣50塊,現在你需要一個4-16的解碼器,你會怎麼選擇:
A: 去小明家買
B: 去小李家買
C: 舉報他倆竟敢賣這麼貴
D: 元器件廠商的一些朋友立刻從海拔下八千米冒了出來並打出了他們家的廣告