Try   HackMD

課程名稱:數位系統與實習

授課教師:黃炳森

參考書籍: Digital Logic Design Using Verilog, Vaibbhav Taraate



🥶計數器 (Counter)

  • 計數器是一種基本的數位電路元件,用於計算事件的發生次數或維護一個數字狀態。計數器通常可以根據其設計分為不同類型,主要包括同步計數器、異步計數器、向上計數器、向下計數器、以及雙向計數器。以下是這些計數器的簡介:
    • 計數器的基本概念 計數器的功能:計數器能夠計算時間、事件或脈衝的數量,並以數字形式表示這些數量。 脈衝觸發:計數器通常是由時鐘信號觸發的,每當時鐘信號有變化(如上升沿或下降沿)時,計數器就會根據其設計的方式增加或減少計數值。

🔴連波進位計數器(Ripple_Carry_Counter)

  • 架構:   連波進位計數器由D型觸發器和一個反向器組成T型正反器再由,串聯T型正反器即可完成。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

  • 連波進位計數器主要模組
module Ripple_Carry_Counter( input clock, reset, output [3:0] q ); T_FF t0(clock, reset, q[0]), t1( q[0], reset, q[1]), t2( q[1], reset, q[2]), t3( q[2], reset, q[3]); endmodule
  • D型觸發器模組
module D_FF( input clock, reset, d, output reg q ); always @(posedge reset or negedge clock) if(reset) q=1'b0; else q=d; endmodule
  • T型觸發器模組
module T_FF( input clock, reset, output q ); wire d; not(d, q); D_FF d1(clock, reset, d, q); endmodule
  • 測試模組
`timescale 1ns/100ps module stimulus; reg clock, reset; wire [3:0] q; Ripple_Carry_Counter RC(clock, reset, q); initial clock=0; always #5 clock=~clock; initial begin reset = 1; #15 reset = 0; #180 reset = 1; #10 reset = 0; #20 $finish; end endmodule
  • 計數器的運作邏輯相對而言我覺得算是困難的,因為涉及了振盪之類的性質,某種程度上也算是有時序的影響,但是多加深入應用自然會有豁然開朗的一天!

👾加法器(Adder)

  • 種類:加法器可分為基本的半加器,全加器(Ripple Carry Adder, CRA)、前瞻進位加法器(Carry Look-Ahead Adder, CLA)、進位選擇加法器(Carry Select Adder, CSA)等。 實務考量:在更高效能的應用中,會使用更複雜的設計如「跳躍進位」(Skip Carry)或「並行進位」(Parallel Carry)來進一步提升效率。

🔵半加法器(Half Adder)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
  • Boolean Function
    Sum=AB
    Cout=AB
module Half_Adder( input A, B, output Sum, Cout ); xor ( Sum, A, B); and (Cout, A, B); endmodule

  依據半法器的真值表和邏輯特性我們可以寫出以上的verilog代碼。

🔵全加法器(Full Adder)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
  • Boolean Function
    Sum=ABCin
    Cout=AB+AC+BC
module Full_Adder( input A, B, Cin, output Sum, Cout ); assign Sum = A^B^Cin; assign Cout = A&B|A&Cin|B&Cin; endmodule

🔴四位元連波進位加法器(4 bits Ripple Full Adder)

RCA

  • 架構   由全加法器依序串聯而成,每一個全加器的進位都會成為下一個全加器的進位輸入之一,而同時每一個全加器都會輸入對應位元的A和B做輸入,並輸出對應位元的Sum。
module Ripple_Full_Adder( input [3:0] A, B, output Cout, output [3:0] Sum ); //調用全加器(詳細請參閱全加器) wire [3:0] c; Full_Adder F0(A[0], B[0], 0, Sum[0], c[1]), F1(A[1], B[1],c[1], Sum[1], c[2]), F2(A[2], B[2],c[2], Sum[2], c[3]), F3(A[3], B[3],c[3], Sum[3], Cout); endmodule

  實作上我們採用階層方的設計,運用上面的全加器電路設計,我們可以輕易的調用出我們需要的數量,但是要注意到每個輸入和輸出的對應關係是否正確。

😈前瞻進位加法器(Carry Look-Ahead Adder, CLA)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
  • boolean function

{C1=G0+P0C0C2=G1+P1G0+P1P0C0C3=G2+P2G1+P2P1G0+P2P1P0C0
{Pi=AiBiGi=AiBiSi=PiCiCi+1=Gi+PiCi

圖片

  理由為可以知道,

PiCi之間可以用來代換全加器,而其中
Ci+1=Gi+CiPi
尤其關鍵,
C1C2C3..
皆可由此推導,以下是推導:

{C1=G0+C0P0C2=G1+C1P1=G1+(G0+C0P0)P1=G1+P1G0+P0P1C0C3=G2+C2P2=G2+(G1+P1G0+P0P1C0)P2=G2+P2G1+P2P1G0+P2P1P0C0

  • 架構   實作上我們將全加法器拆開使用半加法器,以四位元為基礎,我們使用四個半加法器接收4位元數A和B同時輸出各位元的加總和進位,接著我們安裝上超前進位產生器,他可以依據剛剛推論的邏輯電路,高速的運算出各位元的進位數值。

  • CLA主要模組

module CLA( input [3:0] A, B, input C0, output [3:0] Sum, output Cout ); wire [3:0] P, G, C; Half_adder Ha0(A[0], B[0], P[0], G[0]), Ha1(A[1], B[1], P[1], G[1]), Ha2(A[2], B[2], P[2], G[2]), Ha3(A[3], B[3], P[3], G[3]); CLG clg(P, G, C0, C); xor (Sum[0], P[0], C0), (Sum[1], P[1], C[0]), (Sum[2], P[2], C[1]), (Sum[3], P[3], C[2]); buf (Cout, C[3]); endmodule
  • CLA模組的資料流表示法
module CLA( input [3:0] A, input [3:0] B, input C_in, output [3:0] Sum, output Cout ); wire [3:0] P; wire [3:0] G; wire [4:0] C; assign C[0]=C_in; assign Cout=C[4]; genvar i; generate for(i=0;i<4;i=i+1)begin:for_loop assign P[i] = A[i]^B[i]; assign G[i] = A[i]&B[i]; assign Sum[i]= P[i]^C[i]; end endgenerate assign C[1]=G[0]|(P[0]&C[0]), C[2]=G[1]|(P[1]&G[0])|(P[1]&P[0]&C[0]), C[3]=G[2]|(P[2]&G[1])|(P[2]&P[1]&G[0])|(P[2]&P[1]&P[0]&C[0]), C[4]=G[3]|(P[3]&G[2])|(P[3]&P[2]&G[1])|(P[3]&P[2]&P[1]&G[0])|(P[3]&P[2]&P[1]&P[0]&C[0]); endmodule
  • CLG模組
module CLG( input [3:0] P, G, C0, output [3:0] C ); wire [5:0] And; and (And[0], P[0], C[0]), (And[1], P[1], G[0]), (And[2], P[1], P[0], C[0]), (And[3], P[2], G[1]), (And[4], P[2], P[1], G[0]), (And[5], P[2], P[1], P[0], C[0]); or (C[0], G[0], And[0]), (C[1], G[1], And[1], And[2]), (C[2], G[2], And[3], And[4], And[5]); endmodule
  • Half_adder模組
module Half_adder( input A, B, output Sum, Cout ); xor ( Sum, A, B); and (Cout, A, B); endmodule
  • 測試模組
`timescale 1ns/100ps module stimulus; reg [3:0] A, B; reg C0; wire [3:0]Sum; wire Cout; CLA CA(A, B, C0, Sum, Cout); initial begin A=4'd0;B=4'd0;C0=0; end always #50 A<=A+4'd2; always #100 B<=B+4'd3; endmodule

👿十進位加法器(Decimal Adder)

圖片

  • boolea function

    Carry=Cout+Z8Z4+Z8Z2
    S=Z+6

  • 在 BCD 加法中,當兩個 BCD 數字相加的結果大於 1001 時,實際上相當於二進制加法中得到的數值比預期少算了 6。這是因為 BCD 編碼的每個十進位數字只能表示 0 到 9,因此當二進位的和超過 9 時,我們需要將其調整回正確的範圍。

Decimal-Adder-BCD-Adder-6

  • 架構:   在邏輯電路設計的架構上,我們的路徑應該是,一個四位元的連波進位加法器,他會負責處理兩個輸入的計算(請注意此時計算的總和為二進位數),依據真值表我們知道總輸出的進位應該要如何計算,接著只要把計算的Z+Carry就可以轉換為十進位的BCD碼了。

  • 十進位加法器主要模組

module Decimal_Adder( input [3:0] A, B, input Cin, output [3:0] S, output Cout ); wire [3:0] Z; wire C; Ripple_Full_Adder rfa0(A, B, Cin, C, Z); wire [3:0] c; wire A1, A2, O; and (A1, Z[3], Z[2]), (A2, Z[3], Z[1]); or (O, C, A1, A2); assign c = O ? 4'b0110 : 4'b0000; Ripple_Full_Adder rfa1(Z, c, 1'b0, Cout, S); endmodule
  • 連波進位全加法器模組
module Ripple_Full_Adder( input [3:0] A, B, input Cin, output Cout, output [3:0] Sum ); wire [3:0] c; Full_Adder F0(A[0], B[0], Cin, Sum[0], c[1]), F1(A[1], B[1],c[1], Sum[1], c[2]), F2(A[2], B[2],c[2], Sum[2], c[3]), F3(A[3], B[3],c[3], Sum[3], Cout); endmodule
  • 全加法器模組
module Full_Adder( input A, B, Cin, output Sum, Cout ); assign Sum =A^B^Cin; assign Cout =A&B|A&Cin|B&Cin; endmodule
  • 測試模組
`timescale 1ns/100ps module stimulus; reg [3:0] A, B; reg Cin; wire [3:0]S; wire Cout; Decimal_Adder DA(A, B, Cin, S, Cout); initial begin A=4'd0;B=4'd0;Cin=0; end always #50 A<=A+4'd2; always #100 B<=B+4'd3; always #400 Cin<=Cin+1; endmodule
  • 由於該電路涉及多個元件,邏輯關係更為複雜,也更容易出錯,寫程式碼的時候絕對要非常注意和小心!

👻減法器(Subtractor)

  • 減法器(Subtractor)是一種數位邏輯電路,用於在二進制系統中執行減法運算。它和加法器一樣,是構建計算機和數位電路的基本組件之一。減法器可以根據應用需求分為「半減法器(Half Subtractor)」和「全減法器(Full Subtractor)」。

🔵半減法器(Half Subtractor)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
  • boolean function
    Diif=AB
    Borr=AB
module Half_Subtractor( input A, B, output Diff, Borr ); wire BA; not ( BA, A); xor (Diff, A, B); and (Borr, BA, B); endmodule

  實作上是採用類似半加器的邏輯,唯一的差異就是借位時候輸入BA而不是A。

🔴全減法器(Half Subtractor)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
  • boolean function

    Diif=ABBin
    Borr=AB+Bin(AB)

  • 全減器模組

module Full_Subtractor( input A, B, Bin, output Diff, Bout ); wire A1, BA, A2, X2, BX2; xor (Diff, A, B, Bin), ( X2, A, B); not ( BA, A), ( BX2, X2); and ( A1, BA, B), ( A2, Bin, BX2); or (Bout, A1, A2); endmodule
  • 測試模組
`timescale 1ns/100ps module stimulus; reg A, B, Bin; wire Diff, Bout; Full_Subtractor FS(A, B, Bin, Diff, Bout); initial begin A=0;B=0;Bin=0; end always #100 A<=A+1; always #200 B<=B+1; endmodule

  實作上是採用類似全加器的邏輯,但是為了因應borr的邏輯電路,做了比較多的wire去處理,也因此更容易出錯,需要特別留意!

😈連波借位全減法器(Ripple Borrow Full Subtractor)

圖片

  • 架構:   實作方式主要就是串連全減法器,每一位的進位都會被傳入下一位,同時也會輸出每一位的差。

  • 連波全減法器模組

module Ripple_Full_Subtractor( input [3:0] A, B, input Bin, output [3:0] Diff, output Bout ); wire [2:0] Bo; Full_Subtractor FS0(A[0], B[0], Bin, Diff[0], Bo[0]), FS1(A[1], B[1], Bo[0], Diff[1], Bo[1]), FS2(A[2], B[2], Bo[1], Diff[2], Bo[2]), FS3(A[3], B[3], Bo[2], Diff[3], Bout); endmodule
  • 全減器模組
module Full_Subtractor( input A, B, Bin, output Diff, Bout ); wire A1, BA, A2, X2, BX2; xor (Diff, A, B, Bin), ( X2, A, B); not ( BA, A), ( BX2, X2); and ( A1, BA, B), ( A2, Bin, BX2); or (Bout, A1, A2); endmodule
  • 測試模組
`timescale 1ns/100ps module stimulus; reg [3:0] A, B; reg Bin; wire [3:0] Diff; wire Bout; Ripple_Full_Subtractor rfs(A, B, Bin, Diff, Bout); initial begin A=4'd0;B=4'd0;Bin=0; end always #50 A<=A+4'd3; always #100 B<=B+4'd2; endmodule

  實作上是採用類似連波全加器的邏輯,需要同時參照連波進位加法器和全減器

😼加減法器 (Adder-Subtractor)

  • 加減法器(Adder-Subtractor)是一種可以同時執行加法與減法運算的數位電路。在電子工程和數位電路中,加減法器是一個非常重要的元件,常用於計算器、處理器中的算術邏輯單元(ALU),以及各種嵌入式系統中。其運作主要基於全加法器(Full Adder)電路,並利補碼(Two's Complement)來實現減法。

    圖片

  • 架構:   就是主要運用全加法器搭配二的補數的運算概念,因為A-B等同於A+B(B做二的補數)得到的數值,最後,就如同連波進位器我們也需要一個輸出來表達整體最終的進位到下一個運算中,我們可以藉由Cin和Cout的邏輯電路來判斷,當Cin為1時候代表兩數是在做減法,反之同理,但是最後就會注意到計算出來經常會有一個溢位的錯誤需要修正,關於這點我們採用xor(Cout,Cin)即可處理。

  • 加減法器主要模組

module Adder_Subtractor( input [3:0] A, B, input M, output [3:0] Sum, output Cout, Verify ); //使用XOR是因為根據數位邏輯的原理,B'M+BM' 將會是輸出可以產生加減法的效果。 wire [3:0] C, b; xor (b[0], B[0], M), (b[1], B[1], M), (b[2], B[2], M), (b[3], B[3], M), (Verify, Cout, C[2]); Full_Adder FA0(A[0], b[0], M, Sum[0], C[0]), FA1(A[1], b[1], C[0], Sum[1], C[1]), FA2(A[2], b[2], C[1], Sum[2], C[2]), FA3(A[3], b[3], C[2], Sum[3], Cout); endmodule
  • 全加器模組
module Full_Adder( input A, B, Cin, output Sum, Cout ); wire A1, A2, A3; xor (Sum, A, B, Cin); and (A1, A, B), (A2, A,Cin), (A3, B,Cin); or (Cout, A1, A2, A3); endmodule
  • 測試模組
`timescale 1ns/100ps module stimulus; reg [3:0] A, B; reg M; wire [3:0] Sum; wire Cout, Verify; Adder_Subtractor AS(A, B, M, Sum, Cout, Verify); initial begin A=4'b1111;B=4'b0000;M=1; #100 A=4'b1100;B=4'b0011;M=1; #100 A=4'b0011;B=4'b1100;M=1; #100 A=4'b0101;B=4'b0101;M=0; #100 A=4'b1010;B=4'b0101;M=0; #100 A=4'b1101;B=4'b1010;M=0; end endmodule
  • 參考波形圖:
    圖片

🎃乘法器 (Multiplier)

  • 在數位邏輯中,乘法器的目的是計算兩個數的乘積。對於二進制數,乘法的過程類似於十進制的乘法,透過逐位相乘和進位的方式來計算結果。即圖1

🔴二進位乘法器

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
  • 二進位乘法器主要模組
module Binary_Multiplier( input [1:0] A, B, output [3:0] C ); //在22乘法器的and邏輯實現,運來做接下的運算。 wire A1, A2, A3; and (C[0], A[0], B[0]), ( A1, A[0], B[1]), ( A2, A[1], B[0]), ( A3, A[1], B[1]); //引用半加法器單元來做運算,詳細可以參閱數位邏輯 wire carry; Half_Adder HA1(A1, A2, C[1], carry), HA2(A3, carry, C[2], C[3]); endmodule
  • 全加法器(省略)
  • 測試模組
`timescale 1ns/100ps module Mul22_stimulus; reg [1:0] A, B; wire [3:0] C; //測試程式碼用以測試正確性 Binary_Multiplier BM(A, B, C); initial begin A=2'b0;B=2'b0; end always #50 A<=A+1; always #200 B<=B+1; initial $monitor($realtime, " ns, A= %d, B= %d, C= %d", A, B, C); endmodule

  乘法器相對而言其實不是非常複雜,但是一旦位數更多了如何處理將會是一個值得留意的挑戰!

👹多工器 (Multiplexer, MUX)

n_onemultiplexer_blockdiagram

  • 多工器(Multiplexer,簡稱 MUX)和解多工器(Demultiplexer,簡稱 DEMUX)是數位電路中兩種重要的組件。它們在功能上是相對的,主要差異如下:

  • 多工器 (MUX) 功能:多工器是一個選擇器,它根據控制信號選擇一個輸入信號並將其轉換為單個輸出。換句話說,MUX 會將多個輸入信號合併成一個輸出信號。 輸入與輸出:有多個數據輸入(如 2n2n 個)和一個輸出。控制信號的數量 nn 用於選擇哪一個輸入被傳遞到輸出。 示例:一個 2-to-1 多工器有兩個輸入、一個輸出和一個控制信號。根據控制信號的值,選擇其中一個輸入作為輸出。

  • 解多工器 (DEMUX) 功能:解多工器的功能正好與多工器相反。它接收單個輸入信號並根據控制信號將其轉發到多個輸出中。也就是說,DEMUX 可以將一個數據信號分配到多個輸出。 輸入與輸出:有一個數據輸入和多個數據輸出(如 2n2n 個)。控制信號的數量 nn 用於選擇將數據輸出到哪一個具體的輸出端。 示例:一個 1-to-2 解多工器有一個輸入、兩個輸出和一個控制信號。根據控制信號的值,將輸入信號轉發到其中一個輸出。

  • 總結 多工器 是用來選擇輸入信號並將其轉化為單一輸出;而 解多工器 則是用來將單一輸入信號分配到多個輸出。 在實際應用中,多工器通常用於數據路由,而解多工器則用於數據分發。

2 to 1 多工器

圖片

  • 2-1多工器主要模組
module MUL2_1(A, B, S, F); input A, B, S; output F; assign F = ~S & A | S & B; endmodule
  • 測試模組
`timescale 1 ns/100 ps module Test_tb; reg A, B, S; wire F; MUL2_1 UUT(.A(A), .B(B), .S(S), .F(F)); // MUL2_1 UUT(A, B, S, F); initial begin A = 1'b0; B = 1'b0; S = 1'b0; #100 B = 1'b1; #200 B = 1'b0; S = 1'b1; #100 B = 1'b1; #100 B = 1'b0; #100 S = 1'b0; #100 B = 1'b1; end always #100 A <= A + 1; initial #800 $finish; initial $monitor($realtime, "ns %h %h %h %h", A, B, S, F); endmodule

4-to-1 多工器

VwgyX5p
圖片

  • 4-1多工器主要模組
module MUL_4(I, S, F); input [3:0] I; input [1:0] S; output F; wire s1n, s0n; wire y0, y1, y2, y3; not S1n(s1n, S[1]); not S0n(s0n, S[0]); and O0(y0, I[0], s1n, s0n); and O1(y1, I[1], s1n, S[0]); and O2(y2, I[2], S[1], s0n); and O3(y3, I[3], S[1], S[0]); or out(F, y0, y1, y2, y3); endmodule
  • 測試模組
`timescale 1ns/100ps module MUL_4_tb; reg [3:0] I; reg [1:0] S; wire F; MUL_4 ml(I, S, F); initial begin I=4'b0000;S=2'b00; #1200 I=4'b1111; end always #100 I<=I+1'b1; always #300 S<=S+1'b1; initial begin #1600 $finish; $monitor($realtime, "ns %h %h %h", I, S, F); end endmodule

1-to-4 解多工器

圖片

  • 1-4解多工器主要模組
module MUL_1_to_4(I, S0, S1, F0, F1, F2, F3); input I; input S0, S1; output F0, F1, F2, F3; wire s1n, s0n; not (s0n, S0); not (s1n, S1); and(F0, I, s1n, s0n); and(F1, I, s1n, S0); and(F2, I, S1, s0n); and(F3, I, S1, S0); endmodule
  • 測試模組
`timescale 1ns/100ps module MUL_1_to_4_tb; reg I, S0, S1; wire F0, F1, F2, F3; MUL_1_to_4 ml(I, S0, S1, F0, F1, F2, F3); initial begin S0=0;S1=0;I=1; #200 I<=0; end always #50 S0<=S0+1; always #100 S1<=S1+1; initial #400 $finish; endmodule
  • 輸入訊號I依據選擇線的開關被控制導入到特定的輸出口。

👽解碼器 (Decoder)

  • 解碼器(Decoder) 是一種數位邏輯電路,它將二進制數字(通常是n位元)轉換為唯一的輸出信號,通常在一組2^n個輸出中只會有一個輸出為高電平(1),其餘則為低電平(0)。解碼器廣泛應用於計算機系統、存儲器解碼、數據選擇等領域。

🔵二對四解碼器(Decoder2_to_4)

decoder-300x169

  • 2-4解碼器主要模組
module Decoder2_to_4( input A, B, E, output [3:0] D ); wire BA, BB, BE; not (BA, A), (BB, B), (BE, E); nand (D[0], BA, BB, BE), (D[1], BA, B, BE), (D[2], A, BB, BE), (D[3], A, B, BE); endmodule
  • 測試模組
`timescale 1ns/100ps module Decoder2_to_4_tb; reg A, B, E; wire [3:0] D; Decoder2_to_4 De(A, B, E, D); initial begin A=0; B=0; E=0; end always #100 B<=B+1; always #200 A<=A+1; always #400 E<=E+1; endmodule

圖片
圖片

  • 3-8 解碼器主要模組
module Decoder3_to_8( input A, B, C, E, // 增加 C 為輸入 output [7:0] D // 增加輸出為 8 位元 ); wire BA, BB, BC, BE; not (BA, A), (BB, B), (BC, C), (BE, E); // 生成8個輸出 nand (D[0], BA, BB, BC, BE), // 000 (D[1], BA, BB, C, BE), // 001 (D[2], BA, B, BC, BE), // 010 (D[3], BA, B, C, BE), // 011 (D[4], A, BB, BC, BE), // 100 (D[5], A, BB, C, BE), // 101 (D[6], A, B, BC, BE), // 110 (D[7], A, B, C, BE); // 111 endmodule
  • 測試模組
`timescale 1ns/100ps module Decoder3_to_8_tb; reg A, B, C, E; wire [7:0] D; // 將輸出改為 8 位元 Decoder3_to_8 De(A, B, C, E, D); initial begin A = 0; B = 0; C = 0; E = 0; // 初始化所有輸入 end always #100 C <= ~C; // 每100ns反轉 C always #200 B <= ~B; // 每200ns反轉 B always #400 A <= ~A; // 每400ns反轉 A always #800 E <= ~E; // 每800ns反轉 E endmodule

  在概念和功能上解碼器很好理解,就是按照自己的需求可以藉由AND閘去設計類似開關的設計,輸入的邏輯會對應到特定的開關,關鍵在於如何在未來靈活應用到設計中。

編碼器 (Encoder)

🤙比較器(Comparator)

  • 種類:比較器、幅度比較器(Magnitude Comparator)etc.
  • 比較器(Comparator)是一種用於比較兩個數位信號的電路。它可以確定兩個輸入值之間的大小關係,並根據結果輸出相應的信號。比較器通常用於數據處理、數字控制系統和其他需要進行數據比較的應用。

🔵比較器(Comparator)

圖片

  • boolean function

    F1=AB
    F2=F1+F2
    F3=AB

  • 比較器主要模組

module Comparator( input A, B, output FA, FB, FX ); wire BA, BB; not (BA, A), (BB, B); and (FA, BA, B),(FB, BB, A); nor (FX, FA, FB); endmodule

🔴大小比較器(Magnitude Comparator)

圖片

  • 架構:   輸入兩個四位元的二進位數比較他們的大小,邏輯上採用四個比較器分別處理四個位元的邏輯運算,然後因為他們最終要被統一為一個判斷大小的輸出,參考以上圖片完成線路串接即可得到一個可以達成此功能的電路

  • 大小比較器主要模組

module Comparator4_to_4( input [3:0]A, B, output ALB, AGB, AEB ); wire [3:0] FA, FB, FX; wire [6:0] AND; Comparator C3(A[3], B[3], FA[3], FB[3], FX[3]), C2(A[2], B[2], FA[2], FB[2], FX[2]), C1(A[1], B[1], FA[1], FB[1], FX[1]), C0(A[0], B[0], FA[0], FB[0], FX[0]); and (AND[6], FX[3], FA[2]), (AND[5], FX[3], FB[2]), (AND[4], FX[3], FX[2], FA[1]), (AND[3], FX[3], FX[2], FB[1]), (AND[2], FX[3], FX[2], FX[1], FA[0]), (AND[1], FX[3], FX[2], FX[1], FB[0]), ( AEB, FX[3], FX[2], FX[1], FX[0]); or (ALB, FA[3], AND[6], AND[4], AND[2]), (AGB, FB[3], AND[5], AND[3], AND[1]); endmodule
  • 比較器模組
module Comparator( input A, B, output FA, FB, FX ); wire BA, BB; not (BA, A), (BB, B); and (FA, BA, B),(FB, BB, A); nor (FX, FA, FB); endmodule
  • 測試模組
`timescale 1ns/100ps module Comparator4_to_4_tb; reg [3:0] A, B; wire ALB, AGB, AEB; Comparator4_to_4 Comp4(A, B, ALB, AGB, AEB); initial begin A=4'd1;B=4'd3; #50 A=4'd8;B=4'd8; #50 A=4'd3;B=4'd6; #50 A=4'd8;B=4'd4; #50 A=4'd2;B=4'd9; #50 ; end endmodule
  • 比較器整體的設計,就是如同前面的設計思路。

Sequential Logic Circuit(序向電路)

圖片

  • 直到輸入信號切換狀態之前,都可以無限期的維持當前狀態,各種閂鎖與正反器的主要差異在於,輸入數以及這些輸入影響其狀態的方式,而閂鎖屬最基本的元件。
    maxresdefault
module La( input Set, Reset, output reg Q, BQ ); always@(*)begin if(Reset&&Set)begin Q=Q; BQ=BQ; end else if(Reset)begin Q=0; BQ=1; end else if(Set)begin Q=1; BQ=0; end end endmodule
  • 這是基本的SR閂鎖器電路實現
module La_Nand( input Set, Reset, output reg Q, BQ ); wire B_Set, B_Reset; assign B_Set=~Set; assign B_Reset=~Reset; always@(*)begin Q=~(BQ&B_Set); BQ=~( Q&B_Reset); end endmodule
  • 這是NAND型式的實現方式

正反器(Flip-Flop)

image

  • 藉由查看並比較激勵表與布林函數,我們可以系統化的設計序向電路(Sequential Logic Circuit)。

D型正反器

image
image

  • 依據其設計指引,應該至少包含reset、CLK、EN(致能)和基本輸出入,其中需要留意的是當致能的時候,該元件才應該作用,否則應該保存當前狀態。除非此時啟動重置。
    圖片
  • Code
module d_ff( input D, input CLK, input reset, input en, output reg Q, output Qbar ); always@(negedge CLK or negedge reset) begin if(~reset) Q<=0; else if(en) Q<=D; end assign Qbar=~Q; endmodule

圖片

T型正反器

image
image

T型正反器的特點是,當T輸入為1的時候會將當前狀態反轉,當輸入為0的時候則保存當前狀態。

圖片

  • Code
module t_ff( input t, input CLK, input reset, input en, output reg Q //output reg Qbar ); always@(negedge CLK or negedge reset) begin if(~reset) Q<=0; else if(en) begin if(t) Q<=~Q; end end //assign Qbar=~Q; endmodule

圖片

JK正反器

  • JK正反器的狀態變化比較難用一句話描述,但是以下的特性表參閱可以確實幫助分析。
    圖片

image
image

圖片

狀態表實作練習

圖片
圖片

CBA
C+B+A+
DCDBDA
000
100
100
001
xxx
010
011
011
011
000
000
100
111
111
101
xxx
110
xxx
111
010
010

在採用D型正反器的情況下使用卡諾圖化簡:

圖片

同步計數電路

  • 此電路是以01357924680循環為例子:
module Show_Sync( input CLK, input CLRn, output [6:0] Seg ); wire CLKn; wire [3:0] Q; wire [6:0] Seg_tmp; assign Seg=Seg_tmp; Devide50M Div50 (CLK, CLRn, CLKn); Sync02457 Syncnt(CLKn, CLRn, Q); Seg7 seg (Q, Seg_tmp); endmodule module Devide50M( input CLK, input CLRn, output CLKn ); reg [25:0] Count; reg CLKn_tmp; assign CLKn = CLKn_tmp; always@(posedge CLK or negedge CLRn) begin if(!CLRn) begin Count<=0; CLKn_tmp<=0; end else if(Count==24999999) begin Count<=0; CLKn_tmp<=~CLKn_tmp; end else Count<=Count+1; end endmodule module sync4( input CLK, input CLRn, output [3:0] D ); wire JK1; wire JK2; wire JK3; wire [3:0] Dbar; assign JK1=Dbar[1]&Dbar[2]&Dbar[3]; assign JK2=D[0]|D[2]; assign JK3=D[1]&D[2]; JK_flipflop JKA(CLK, CLRn, JK1, D[3], D[0], Dbar[0]), JKB(CLK, CLRn, JK2, 1'b1, D[1], Dbar[1]), JKC(CLK, CLRn,D[1], D[1], D[2], Dbar[2]), JKD(CLK, CLRn, JK3, 1'b1, D[3], Dbar[3]); endmodule module jk_ff( input CLK, input CLRn, input J, input K, output reg Q, output Qbar ); assign Qbar=~Q; always@(negedge CLK or negedge CLRn) begin if(!CLRn) Q<=0; else case({J,K}) 2'b00:Q<=Q; 2'b01:Q<=0; 2'b10:Q<=1; 2'b11:Q<=~Q; endcase end endmodule module Seg7( input [3:0] Signal, output reg [6:0] Seg ); always@(*)begin case(Signal) 4'h0 :Seg=7'b1000000; 4'h1 :Seg=7'b1111001; 4'h2 :Seg=7'b0100100; 4'h3 :Seg=7'b0110000; 4'h4 :Seg=7'b0011001; 4'h5 :Seg=7'b0010010; 4'h6 :Seg=7'b0000010; 4'h7 :Seg=7'b1111000; 4'h8 :Seg=7'b0000000; 4'h9 :Seg=7'b0010000; 4'hA:Seg=7'b0100000; 4'hB:Seg=7'b0000011; 4'hC:Seg=7'b1000110; 4'hD:Seg=7'b0100001; 4'hE:Seg=7'b0000110; 4'hF:Seg=7'b0001110; endcase end endmodule
  • 034567

圖片

CBA
QCQBQA
JCKC
JBKB
JAKA
000
011
0X
1X
1X
001
XXX
XX
XX
XX
010
XXX
XX
XX
XX
011
100
1X
X1
X1
100
101
X0
0X
1X
101
110
X0
1X
X1
110
111
X0
X0
1X
111
000
X1
X1
X1

圖片

module sync_c3( input CLK, input CLRn, output [2:0] Q, output [2:0] Qbar ); wire JB=Q[0]|Qbar[2]; wire JC=Q[0]; wire KB=Q[0]; wire KC=Q[0]&Q[1]; JK_FF JKA(CLK, CLRn, 1'b1, 1'b1, Q[0], Qbar[0]), JKB(CLK, CLRn, JB, KB, Q[1], Qbar[1]), JKC(CLK, CLRn, JC, KC, Q[2], Qbar[2]); endmodule module JK_FF( input CLK, input CLRn, input J, input K, output reg Q, output Qbar ); assign Qbar=~Q; always@(posedge CLK or negedge CLRn) begin if(!CLRn) Q<=1'b0; else case({J,K}) 2'b00:Q<=Q; 2'b01:Q<=0; 2'b10:Q<=1; 2'b11:Q<=~Q; endcase end endmodule

圖片
圖片

非同步清除3位元同步上數計數器

圖片

  • 使用D型正反器實現,正反器功能包含清除功能,輸入由真值表化簡得出。
  • 以下提供具體程式模組和測試模組:
module Sync3( input CLK, input CLRn, output [2:0] Q ); wire [2:0] Qbar; wire Dc; wire Db; assign Dc=(Q[2]&Qbar[0])|(Q[2]&Qbar[1])|(Qbar[2]&Q[0]&Q[1]); assign Db=Q[0]^Q[1]; d_FF dA(CLK, CLRn, Qbar[0], Q[0], Qbar[0]), dB(CLK, CLRn, Db, Q[1], Qbar[1]), dC(CLK, CLRn, Dc, Q[2], Qbar[2]); endmodule module d_FF( input CLK, input CLRn, input D, output reg Q, output Qbar ); assign Qbar=~Q; always@(posedge CLK or negedge CLRn) begin if(!CLRn) Q<=0; else Q<=D; end endmodule `timescale 1ns/10ps module stimulus; reg CLK; reg CLRn; wire [2:0] Q; Sync3 Sy3(CLK, CLRn, Q); initial begin CLK <=0; CLRn<=1; end always #5 CLK<=~CLK; initial #70 CLRn<=0; endmodule

FINITE STATE MACHINES(FSM)

  • 有限狀態機描述的是一個電路其狀態可以依據暫存器的數量來展現。接續這個概念,通常有兩個類型 Moore Machines 和 Mealy Machines 其差異可以先觀察下圖。
    圖片
  • 前者輸出的信號只受到電路的當前狀態影響,但是後者輸出信號卻同時受到輸入信號和當前狀態影響。

FSM DESIGN EXAMPLE

  • 課本有舉例一個範例來實現 FSM 的設計流程,讓我們開始來看看吧。

Football players are hustling between theathletic fields and the dining hall on Bravado Boulevard. They are tossingthe ball back and forth and aren’t looking where they are going either.Several serious injuries have already occurred at the intersection of these two roads, and the Dean of Students asks BenBitdiddle to install a trafficlight before there are fatalities.

  • 當前問題就是,有一群討厭的足球員在未妥善安裝紅綠燈的路口瞎鬧,導致交通意外頻傳,所以我們需要使用FSM的概念,在重大傷亡意外出現前設計出紅綠燈系統。

  • 首先分別在 Academic Ave and Bravado Blvd 安置兩個道路傳感器

    TA and
    TB
    如果在傳感器上有學生就會回傳 TRUE 否則回傳 FALSE,每個燈號會依據傳感器的輸入信號來輸出紅色、綠色、或黃色。因此這個 FSM 會有兩個 input
    TA
    and
    TB
    以及兩個 output
    LA
    and
    LB
    如下圖呈現。並且CLOCK信號週期為5秒,並加上一個重置的控制鍵方便相關技術人員能夠確保該裝置狀態能被初始化。依照描述我們可以開始專注到呈現狀態轉移表。
    圖片
    圖片

  • 當信號重置,

    LA為綠燈
    LB
    為紅燈,變換燈號時,綠燈那方會先變成黃燈5秒然後變紅燈,同時紅燈方會轉變為綠燈。過程中傳感器不斷確認是否行人通過直到沒有行人才會切換狀態。
    圖片

  • 藉由觀察狀態轉移流程圖我們可以重寫一個狀態表如下圖,同時依照FSM的概念我們必須以符合暫存器規範的形式描述狀態所以如下圖我們要轉換二進位的編碼表。

    圖片
    圖片
    圖片

  • 統整輸出信號的boolean equ

    圖片
    圖片

  • 可以化簡為

    圖片
    圖片

  • 統整以上結果實現電路圖:

    圖片
    圖片

  • 有限狀態機描述的是一個電路其狀態可以依據暫存器的數量來展現。

暫存器(Register)

  • 暫存器(Register)是數位電路中的一種基本元件,用來儲存二進位資料。它由一組觸發器(通常是D型觸發器)構成,能在時鐘信號的控制下儲存數據。暫存器常見於處理器、記憶體單元以及數位控制系統中。
    圖片
    圖片

32位元暫存器設計

圖片

  • 功能說明: 由四個8位元暫存器 A, B, C, D組成,並且附帶一個暫存器V、以及選擇線,依據選擇線V會讀取A, B, C, D的資料,實現基礎的資料轉移。
module register #(parameter WIDTH=32, RLo=8)( input CLK, input CLRn, input CE, input [WIDTH-1:0] D, input [NUM_SLsg-1:0] SLsg, output [RLo-1:0] V, output [RLo-1:0] Vbar, output [WIDTH-1:0] Q, output [WIDTH-1:0] Qbar ); localparam NUM_SLsg=WIDTH/RLo; wire [RLo-1:0] QA; wire [RLo-1:0] QB; wire [RLo-1:0] QC; wire [RLo-1:0] QD; wire [RLo-1:0]BQA; wire [RLo-1:0]BQB; wire [RLo-1:0]BQC; wire [RLo-1:0]BQD; assign Q={QD, QC, QB, QA}; assign Qbar={BQD, BQC, BQB, BQA}; register8 #(RLo) regA (CLK, CLRn, CE, D[7:0], QA, BQA), regB (CLK, CLRn, CE, D[15:8], QB, BQB), regC (CLK, CLRn, CE, D[23:16], QC, BQC), regD (CLK, CLRn, CE, D[31:24], QD, BQD); register8_V #(WIDTH, RLo, NUM_SLsg) regV (QA, QB, QC, QD, SLsg, V, Vbar); endmodule module Slect_Segment #(parameter RLo, NUM_SLsg)( input [RLo-1:0] QA, input [RLo-1:0] QB, input [RLo-1:0] QC, input [RLo-1:0] QD, input [NUM_SLsg-1:0] SLsg, output reg [RLo-1:0] TemV ); always@(SLsg) case(SLsg) 2'b00:TemV<=QA; 2'b01:TemV<=QB; 2'b10:TemV<=QC; 2'b11:TemV<=QD; default: TemV = {RLo{1'b0}}; endcase endmodule module register8 #(parameter WIDTH)( input CLK, input CLRn, input CE, input [WIDTH-1:0] D, output reg [WIDTH-1:0] Q, output [WIDTH-1:0] Qbar ); inverter #(WIDTH) invQ(Q, Qbar); always @(posedge CLK or negedge CLRn) begin if (!CLRn) Q <= {WIDTH{1'b0}}; else if (CE) Q <= D; end endmodule module register8_V #(parameter WIDTH, RLo, NUM_SLsg)( /*input CLK, input CLRn, input CE,*/ input [RLo-1:0] QA, input [RLo-1:0] QB, input [RLo-1:0] QC, input [RLo-1:0] QD, input [NUM_SLsg-1:0] SLsg, output [WIDTH-1:0] Q, output [WIDTH-1:0] Qbar ); inverter #(WIDTH) invQ(Q, Qbar); Slect_Segment #(RLo, NUM_SLsg) S1 (QA, QB, QC, QD, SLsg, Q); endmodule module inverter #(parameter WIDTH)( input [WIDTH-1:0] Qin, output [WIDTH-1:0] Qout ); assign Qout = ~Qin; endmodule

8位元微處理機基本架構設計

  • 支援四個功能 ADD, SUB, OR, AND,只有一個累加器(acc)和程式計數器(pc)。只使用一個CLK週期。

處理機結構

  • Control Unit, CU, 採用簡化的FSM來達成硬體控制的功能。
  • Arithmetic Logic Unit, ALU, 專注於ADD, SUB, OR, AND等運算功能的實現即可。
  • Memory 採用唯讀記憶體存放指令。
  • Registers 實現ACC, PC, IR 等功能為目標。