小梅哥——38译码器
-
三八譯碼器,即是 3 種輸入狀態翻譯成 8 種輸出狀態。
-
真值表
-
代碼展示
module decoder_3_8(a,b,c,out);input a;//輸入端口ainput b;//輸入端口binput c;//輸入端口coutput [7:0] out;//輸出端口outreg [7:0] out;//或者用output reg [7:0] out//以always塊描述的信號賦值,被賦值的對象必須要定義成reg類型
always@(a,b,c)begin //相當于always@(*),*就代指以上所有輸入變量case({a,b,c})//位拼接,{a,b,c}變成了一個三位的信號3'b000:out = 8'b0000_0001;3'b001:out = 8'b0000_0010;3'b010:out = 8'b0000_0100;3'b011:out = 8'b0000_1000;3'b100:out = 8'b0001_0000;3'b101:out = 8'b0010_0000;//3'd5 :out = 8'b0010_00003'b110:out = 8'b0100_0000;3'b111:out = 8'b1000_0000;/* 3'd0:out = 8'b0000_0001;//下劃線 _ 是為了增強代碼的可讀性。3'd1:out = 8'b0000_0010;3'd2:out = 8'b0000_0100;3'd3:out = 8'b0000_1000;3'd4:out = 8'b0001_0000;3'd5:out = 8'b0010_0000;3'd6:out = 8'b0100_0000;3'd7:out = 8'b1000_0000; //注意這里的跨行注釋方法 /*和*/*/endcaseend
endmodule
testbench
`timescale 1ns/1ns
module decoder_3_8_tb();reg s_a;reg s_b;reg s_c;wire [7:0] out;decoder_3_8 decoder_3_8(.a(s_a),.b(s_b),.c(s_c),.out(out));initial begins_a=0;s_b=0;s_c=0; //在0時刻三個輸入均為0#200; //經過200ns的延時s_a=0;s_b=0;s_c=1; //在200ns時輸入信號的值#200; //又經過200ns的延時s_a=0;s_b=1;s_c=0; //在400ns時輸入信號的值#200; //又經過200ns的延時s_a=0;s_b=1;s_c=1; //在600ns時輸入信號的值#200;s_a=1;s_b=0;s_c=0;#200;s_a=1;s_b=0;s_c=1;#200;s_a=1;s_b=1;s_c=0;#200;s_a=1;s_b=1;s_c=1;#200; $stop; //停止仿真end
endmodule
-
仿真圖
-
補充
(1)always語句兩種觸發方式
a、第一種是電平觸發,例如always @(a or b or c),a、b、c均為變量,當其中一個發生變化時,下方的語句將被執行。
b、第二種是沿觸發,例如always @(posedge clk or negedge rstn),即當時鐘處在上升沿或下降沿時,語句被執行。
c、而對于always@(),意思是以上兩種觸發方式都包含在內,任意一種發生變化都會觸發該語句。
(2)數字聲明
數字聲明時,合法的基數格式有 4 種,包括:十進制('d 或 'D),十六進制('h 或 'H),二進制('b 或 'B),八進制('o 或 'O)。
數字10的不同表示方式,'前面的數字表示位數,'后面的一個字母字母表示進制格式
b 二進制 4'b1010
0 八進制 2'o12
d 十進制 2'd10
h 十六進制 1'ha
(3)數值的種類
wire 和reg這兩種數據類型的變量在定義時要設置位寬,缺省為1位。變量的每一位可以是0,1,X,Z。其中x代表一個未被預置初始狀態的變量或者是由于由兩個或多個驅動裝置試圖將之設定為不同的值而引起的沖突型線型變量。z代表高阻狀態或浮空量
Verilog HDL 有下列四種基本的值來表示硬件電路中的電平邏輯:
0:邏輯 0 或 "假"
1:邏輯 1 或 "真"
x 或 X:未知
z 或 Z:高阻
x 意味著信號數值的不確定,即在實際電路里,信號可能為 1,也可能為 0。
z 意味著信號處于高阻狀態,常見于信號(input, reg)沒有驅動時的邏輯結果。例如一個 pad 的 input 呈現高阻狀態時,其邏輯值和上下拉的狀態有關系。上拉則邏輯值為 1,下拉則為 0 。
(4)數據的類型
Verilog 最常用的 2 種數據類型就是線型(wire)與寄存器型(reg),其余類型可以理解為這兩種數據類型的擴展或輔助。
a、線網(wire)使用在連續賦值語句中
相當于一根電線,用來連接電路,不能存儲數據,無驅動能力,只能在assign左側賦值。
wire型數據常用來表示以assign關鍵字指定的組合邏輯信號。模塊的輸入輸出端口類型都默認為wire型(默認初始值是z)不指定就默認為1位wire類型,專門指定出wire類型,可能是多位或為使程序易讀。
wire表示直通,即只要輸入有變化,輸出馬上無條件地反映。
線網型還有其他數據類型,包括 wand,wor,wri,triand,trior,trireg 等。這些數據類型用的頻率不是很高。
b、寄存器(reg)使用在過程賦值語句中
always模塊內被賦值的信號,必須定義為reg型,默認初始值是x。
reg表示一定要有觸發,輸出才會反映輸入。
reg只能在initial和always中賦值。
reg可以綜合成register,latch,甚至wire(當其只是中間變量的時候),可以用于組合邏輯或者時序邏輯,能存儲數據,有驅動能力,在always @模塊表達式左側被賦值。
寄存器(reg)用來表示存儲單元,它會保持數據原有的值,直到被改寫。
c、兩者的共同點
都能用于assign與always @模塊表達式的右側。
d、連續賦值語句和過程賦值語句
在連續賦值語句中,表達式右側的計算結果可以立即更新表達式的左側。在理解上,相當于一個邏輯之后直接連了一條線,這個邏輯對應于表達式的右側,而這條線就對應于wire。
在過程賦值語句中,表達式右側的計算結果在某種條件的觸發下放到一個變量當中,而這個變量可以聲明成reg類型的。根據觸發條件的不同,過程賦值語句可以建模不同的硬件結構:如果這個條件是時鐘的上升沿或下降沿,那么這個硬件模型就是一個觸發器;如果這個條件是某一信號的高電平或低電平,那么這個硬件模型就是一個鎖存器;如果這個條件是賦值語句右側任意操作數的變化,那么這個硬件模型就是一個組合邏輯。
e、綜合之后的區別
wire型的變量綜合出來一般是一根導線;
reg變量在always塊中有兩種情況: always后的敏感表中是(a or b or c)形式的,也就是不帶時鐘邊沿的,綜合出來還是組合邏輯 always后的敏感表中是(posedge clk)形式的,也就是帶邊沿的,綜合出來一般是時序邏輯,會包含觸發器(Flip-Flop)
在設計中,輸入信號一般來說你是不知道上一級是寄存器輸出還是組合邏輯輸出,那么對于本級來說就是一根導線,也就是wire型。而輸出信號則由你自己來決定是寄存器輸出還是組合邏輯輸出,wire型、reg型都可以。但一般的,整個設計的外部輸出(即最頂層模塊的輸出),要求是寄存器輸出,較穩定、扇出能力也較好。
(5)
輸入端口可以由net/reg驅動,但輸入端口只能是net,如a = b & c,輸入端口a 只能是net型,但其驅動b,c可以是net/reg型;
輸出端口可以使net/reg類型,輸出端口只能驅動net,如a = b & c,模塊的輸出端口b,c可以是net/reg型,但它們驅動的a必須是net型;若輸出端口在過程塊(always/initial)中賦值則為reg型,若在過程塊外賦值則為net型。用關鍵詞inout聲明一個雙向端口, inout端口不能聲明為寄存器類型,只能是net類型。
(6)課后作業
實現4-16譯碼器
a、原理框圖
`timescale 1ns / 1ns
module decoder_4_16(a,b,c,d,out);input a;input b;input c;input d;output reg[15:0] out;
always@(a,b,c,d)begincase({a,b,c,d})4'b0000:out=16'b0000_0000_0000_0001;4'b0001:out=16'b0000_0000_0000_0010;4'b0010:out=16'b0000_0000_0000_0100;4'b0011:out=16'b0000_0000_0000_1000;4'b0100:out=16'b0000_0000_0001_0000;4'b0101:out=16'b0000_0000_0010_0000;4'b0110:out=16'b0000_0000_0100_0000;4'b0111:out=16'b0000_0000_1000_0000;4'b1000:out=16'b0000_0001_0000_0000;4'b1001:out=16'b0000_0010_0000_0000;4'b1010:out=16'b0000_0100_0000_0000;4'b1011:out=16'b0000_1000_0000_0000;4'b1100:out=16'b0001_0000_0000_0000;4'b1101:out=16'b0010_0000_0000_0000;4'b1110:out=16'b0100_0000_0000_0000;4'b1111:out=16'b1000_0000_0000_0000;/* 2'd00:out=16'b0000_0000_0000_0001;2'd01:out=16'b0000_0000_0000_0010;2'd02:out=16'b0000_0000_0000_0100;2'd03:out=16'b0000_0000_0000_1000;2'd04:out=16'b0000_0000_0001_0000;2'd05:out=16'b0000_0000_0010_0000;2'd06:out=16'b0000_0000_0100_0000;2'd07:out=16'b0000_0000_1000_0000;2'd08:out=16'b0000_0001_0000_0000;2'd09:out=16'b0000_0010_0000_0000;2'd10:out=16'b0000_0100_0000_0000;2'd11:out=16'b0000_1000_0000_0000;2'd12:out=16'b0001_0000_0000_0000;2'd13:out=16'b0010_0000_0000_0000;2'd14:out=16'b0100_0000_0000_0000;2'd15:out=16'b1000_0000_0000_0000;*/endcase
end
endmodule
`timescale 1ns / 1nsmodule decoder_4_16_tb();reg s_a;reg s_b;reg s_c;reg s_d;wire [15:0] out; decoder_4_16 decoder_4_16(.a(s_a),.b(s_b),.c(s_c),.d(s_d),.out(out));initial begins_a=0;s_b=0;s_c=0;s_d=0;#100;s_a=0;s_b=0;s_c=0;s_d=1;#100;s_a=0;s_b=0;s_c=1;s_d=0;#100;s_a=0;s_b=0;s_c=1;s_d=1;#100;s_a=0;s_b=1;s_c=0;s_d=0;#100;s_a=0;s_b=1;s_c=0;s_d=1;#100;s_a=0;s_b=1;s_c=1;s_d=0;#100;s_a=0;s_b=1;s_c=1;s_d=1;#100;s_a=1;s_b=0;s_c=0;s_d=0;#100;s_a=1;s_b=0;s_c=0;s_d=1;#100;s_a=1;s_b=0;s_c=1;s_d=0;#100;s_a=1;s_b=0;s_c=1;s_d=1;#100;s_a=1;s_b=1;s_c=0;s_d=0;#100;s_a=1;s_b=1;s_c=0;s_d=1;#100;s_a=1;s_b=1;s_c=1;s_d=0;#100;s_a=1;s_b=1;s_c=1;s_d=1;#100; end
endmodule
總結
以上是生活随笔為你收集整理的小梅哥——38译码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【学习笔记】左偏树的可持久化(【模板】k
- 下一篇: pyautogui 鼠标键盘自动化 库的