這是一個真實故事 !

最近房間的警報器故障不響了, 主要觸動警報器的條件有三個 ,一客廳, 二廚房,三大門的近接開關 ,只要有一個被開啟 ,就會唱一段歌 ,然後結束! 直到三個開關都關閉後 ,下次任一個開關被打開時 ,才會又唱一次 !! 我在想這該如何製作呢? 以前記得叫學生設計過寫十字路口紅綠燈控制器 ,現在都AI啥時代了 ! 還用TTL兜 ?!! @@ 我可是有工業電子乙級 ,高級邏輯設計的經驗呦 ,於是乎……


begin:
bz=0 ;警報器
if A or B or C = 0 then ;A/B/C 開關
bz=1 ;響一次
else go begin


Q請轉成程式語言中(例如 Python)
您提供的邏輯通常會使用 while 迴圈來達成重複執行的效果。以下是轉換後的程式碼:
python
while True:
bz = 0
# 檢查 A、B 或 C 是否任一為 0
if A == 0 or B == 0 or C == 0:
bz = 1
break # 條件成立,設定 bz=1 並跳出迴圈(相當於結束程式或往下執行)
else:
continue # 條件不成立,回到迴圈開頭重新執行(相當於 go begin)

這段可能會讓警報器唱不停, 沒關係, 另外加個RC timer 或往下再加bz=0就可以, 嗯~~ 還可以用 .

Q再來便是重點, 請轉成邏輯線路….

要將這段帶有條件判斷與狀態鎖定/循環(Feedback/Latch)的程式碼轉成硬體邏輯線路,我們必須先將軟體邏輯化簡為數位電路的訊號關係。
核心結論:此邏輯在電路中等同於一個「由 A、B、C 觸發的 RS 鎖存器(RS Latch)」。
當 (A=0) 或 (B=0) 或 (C=0) 時,輸出 (bz) 會被設定為 (1) 並不永久保持(鎖定),回到開頭(響應後續變化)。

1. 邏輯條件化簡
1. 偵測條件(判斷 A, B, C 是否任一為 0):
o 「或」的關係:( ext{Trigger} = ar{A} + ar{B} + ar{C})。
o 根據德摩根定律(De Morgan's laws),這也等同於將 A、B、C 輸入一個 反及閘(NAND Gate):( ext{Trigger} = overline{A cdot B cdot C})。
2. 狀態保持(bz = 1 且不再 go begin):
o 軟體中的 else go begin 代表在條件不滿足前,不停重複檢查。一旦條件滿足,bz = 1 並且程式結束(跳出)。
o 在硬體中,這代表一個鎖存(Latch)機制。一旦觸發訊號來了,(bz) 變為 1,之後不論 A, B, C 怎麼變,(bz) 都必須維持 1。
o 反之 就不要用含latch功能的FFlop.

閘級詳細電路圖(Gate-Level Diagram)
如果用最基礎的或閘(OR)、反閘(NOT)與反或閘(NOR)構成的 Latch 來繪製,線路如下:

text
A ─── [NOT] ───┐
├─── [ 3輸入 OR 閘 ] ─── (S) ───┐
B ─── [NOT] ───┤ │
│ ▼
C ─── [NOT] ───┘ ┌─────┐
┌──────┤ NOR ├─────┐─── bz 輸出
│ └─────┘ │
│ │
└───╳──────────────┘

┌───┴─┐
RESET ────────┤ NOR ├
└─────┘

這是一個真實故事 !這是一個真實故事 !

Q如果想用 Verilog / VHDL 碼,或是想加上時脈同步(Clock/Flip-Flop)的硬體設計?

1. 硬體邏輯行為設計 (D 正反器 + 狀態反饋)
為了達到「一旦變為 1 就持續鎖定在 1(除非 Reset)」以及「時脈同步」的要求,我們可以使用一個 D 正反器(D Flip-Flop) 搭配組合邏輯。
• 觸發條件 (Trigger): 當 A=0 或 B=0 或 C=0 時觸發,邏輯表示式為 (overline{Acdot Bcdot C})(使用一個 3 輸入反及閘 NAND)。
• D 輸入端邏輯 (D-Input):
為了讓 bz 變成 1 後就鎖定,我們將「觸發條件」與「目前的輸出 bz」做或閘(OR)運算。(D= ext{Trigger}+bz)
同步電路圖 (Clocked Circuit Diagram)

text
A ───┐
B ───┼─ [ 3輸入 NAND ] ── (Trigger) ───┐
C ───┘ │

┌───────┐
bz ───┐ │ OR 閘 │
▼ └───┬───┘
┌────┴────┐ │
│ 保持鎖定 │ │
└─────────┘ ▼
┌───D───┐
│ │
CLK ───────►│ DFF ├───────► bz (輸出)
│ │
RESET ───────┤RST │
└───────┘

這是一個真實故事 !這是一個真實故事 !
運作機制
1. 非同步重設 (Reset): 當系統啟動或重設時,RESET 訊號會將 DFF 清零,此時 bz = 0。
2. 時脈運行 (Clocking):
o 如果 A, B, C 都是 1,Trigger 為 0。在時脈上升緣到來時,D = 0 + bz,所以 bz 保持原本的 0(這就是軟體的 else go begin)。
o 一旦 A, B, C 任一變為 0,Trigger 變為 1。在下一個時脈上升緣,1 被鎖存進 DFF,輸出 bz 變為 1。
o 當 bz 變為 1 後,因為 D = Trigger + 1 = 1,不論之後 A、B、C 如何變化,D 端永遠輸入 1,bz 將永久維持 1。
_____________________________________

2. Verilog 程式碼實作
在數位 IC 設計中,我們會用硬體描述語言(Verilog)來撰寫這個同步電路:
verilog
module bz_logic (
input wire clk, // 時脈訊號
input wire rst_n, // 低電位有效的非同步重設訊號 (Reset)
input wire A,
input wire B,
input wire C,
output reg bz // 暫存器型態的輸出
);

// 定義觸發條件:當 A, B, C 任一為 0 時 (等同於 NAND 邏輯)
wire trigger;
assign trigger = (!A || !B || !C);

// 時脈同步區塊:只在時脈上升緣或重設觸發時執行
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
bz <= 1'b0; // 重設時,bz 初始化為 0 (對應軟體開頭 bz=0)
end else begin
if (trigger) begin
bz <= 1'b1; // 條件滿足,設定 bz = 1
end else begin
bz <= bz; // 條件不滿足,維持原值 (對應軟體 go begin 循環)
end
end
end

endmodule


想到這…….已經心有戚戚焉了 ,尤其對一位熟透組合邏輯的老硬體工程師 , 熟捻序向邏輯的資深技工,

當年的電子工程苦學 , 似乎已經完全用不上了, 現在只要用問的 , 提需求 (講台語耶嘛通) , 管你是第幾類組 , 就都能產生實用的線路……

記得當年日本人用FF 兜出 DRAM Refresh線路得時候, 我卻只用PLD + C 語言就描述出對應用的線路, 而且列印出線路圖紙後居然沒人看得懂 (包含我自己) 在當時可是被列為神人等級的呦 , 事隔多年 AI 演變快 ,學習多, 記得勞 ,衍生迅速 , 真的可以收工了 ~~~

以前設計IC 外還要連test pattern也要自己寫 , 不騙你 ! 更糟的是 , 如果設計 DRAM Controller你還要寫DRAM模組 , 證明讀寫沒有問題 ! 而且要-20ns, -10ns and -3ns通通包 , 以增加 Coverage rate.

還有啊設計彩色掃描器, 要接收Color Sensor的 R/G/B訊號 ,難得是要處理18線距的影像 (18 lines gap), 也就是一條掃描線 ,是 R (-18) + G (1) + B(+18) 組合後才是真正的第一條可以印出來的線 ,也就是掃描器要掃18次 ,才會又第一條線輸出….. 呵呵….. 這樣要靠TTL兜出來, 真的很累 ,現在可就輕鬆了 !


為了測試與驗證這個同步時脈電路,我們需要撰寫一個 Testbench(測試平台)。Testbench 的主要功能是產生模擬的時脈、重設訊號,以及變換 A、B、C 的輸入值,讓我們可以在模擬軟體中觀察波形。

以下為您提供 Verilog 測試平台 (Testbench) 原始碼,以及完整的波形分析說明。
__________________________________
1. Verilog Testbench 原始碼 (tb_bz_logic.v)
這個測試平台會自動生成 50MHz 的時脈,並依序模擬:初始化 ➔ 正常維持 ➔ 觸發變更 ➔ 撤銷輸入但維持鎖定 的完整過程。
verilog
`timescale 1ns / 1ps // 設定時間單位為 1ns,時間精確度為 1ps

module tb_bz_logic;

// 1. 宣告連接到被測模組 (DUT) 的訊號
reg clk;
reg rst_n;
reg A;
reg B;
reg C;
wire bz;

// 2. 實例化被測模組 (Design Under Test, DUT)
bz_logic uut (
.clk(clk),
.rst_n(rst_n),
.A(A),
.B(B),
.C(C),
.bz(bz)
);

// 3. 產生時脈訊號 (Clock Generator)
// 週期為 20ns,代表 50MHz 的時脈
always begin
#10 clk = ~clk;
end

// 4. 測試激勵訊號產生 (Test Stimulus)
initial begin
// ─── 步驟 A: 初始狀態 ───
clk = 0;
rst_n = 0; // 觸發低電位重設
A = 1;
B = 1;
C = 1;
#25; // 等待 25ns (確保渡過第一個時脈上升緣)

rst_n = 1; // 結束重設,電路開始正常運作
#20; // 此時 A=1, B=1, C=1,bz 應該保持 0 (go begin 循環)

// ─── 步驟 B: 測試觸發條件 ───
A = 0; // 讓 A 變為 0 (滿足 A or B or C == 0)
#20; // 等待一個時脈週期,此時 bz 應該在時脈上升緣跳變為 1

// ─── 步驟 C: 測試鎖定機制 (Locking) ───
A = 1; // 把 A 變回 1,讓 A, B, C 全為 1 (原本應該走 else go begin)
#40; // 等待兩個時脈週期,觀察 bz 是否依然死鎖在 1

// ─── 步驟 D: 再次施加外部重設 ───
rst_n = 0; // 再次重設
#20; // bz 應該立刻回到 0
rst_n = 1; // 釋放重設
#40;

// 結束模擬
$display("模擬結束!請檢查波形視窗。");
$finish;
end

endmodule

____________________________________
2. 預期的模擬波形與時間軸分析
當您在軟體中執行此模擬時,波形在以下時間點會產生對應的變化:
時間軸 (Time) 輸入訊號狀態 (rst_n, A, B, C) 輸出 bz狀態 電路行為說明
0 ~ 25ns rst_n=0, A=1, B=1, C=1 0 系統重設中: 異步重設啟動,bz 強制初始化為 0。
25 ~ 45ns rst_n=1, A=1, B=1, C=1 0 Go Begin 循環: 條件不滿足,在 30ns 的時脈上升緣,bz 保持為 0。

45 ~ 65ns rst_n=1, A=0, B=1, C=1 1 觸發鎖定: 45ns 時 A 變為 0。在 50ns 的時脈上升緣,電路偵測到觸發,bz 躍升為 1。

65 ~ 105ns rst_n=1, A=1, B=1, C=1 1 狀態死鎖: 雖然 A 變回 1 使得觸發條件消失,但在 70ns、90ns 的時脈上升緣,bz 成功自我鎖定,維持為 1。

105ns 之後 rst_n=0 0 重新初始化: 外部重設再次按下,bz 瞬間被清零,電路重回 begin 狀態。

這是一個真實故事 !這是一個真實故事 !
___________________________________

接下來,如果您需要針對這個電路進行 FPGA 腳位綁定 (Constraint),或者想了解如何把它包裝成一個可重複呼叫的子功能模組 (Sub-module)!

我的天啊 ~~~ 我想以後你可以告訴老闆 我們在咖啡廳等他了 ………..

附上公園放空隨想慢走 , 與主題不合照 ! Sorry :)


這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !

這是一個真實故事 !
還是要低調一點,不然會被認定成多餘的工作岡位,往後老闆要開源節流時,會被排到名單中
Scott Lin a
沒錯 躲一下
Scott Lin a wrote:
這是粗體字這是一個真實故事 !這是粗體字


這是一個真實故事 !

樓主都這麼會寫程式了,連html的基本語法都不會?
Scott Lin a
忘了寫偵錯程式了 [大哭]
因為樓主是老司機,知道怎麼下正確的指令叫ai做吧
這個是要訓練的

雖然ai厲害到可以取代初階人才,但是高階人才還是要從初階開始培養
不然就會斷層了
Scott Lin a
所言甚是![^++^]
文章分享
評分
評分
複製連結

今日熱門文章 網友點擊推薦!