Design 03 tháng 9, 2026 ⟳ 14 phút đọc

Power-on reset: mạch phải làm việc trước khi được phép làm việc

POR là khối vài transistor không nằm trong signal path nhưng quyết định chip lên đúng hay lên rác. Mình dựng con RC-POR ngây thơ trên sky130 rồi cho nguồn dốc ở nhiều tốc độ: có tốc độ nó reset ngon, có tốc độ nó không hề reset — và một cú sụt nguồn 60µs thì nó ngủ quên.

power-on resetbrown-outsky130ngspicestartupreliability
Nhận bài viết mới

Không spam. Chỉ bài kỹ thuật AMS đáng đọc — gửi qua email khi có bài mới.

Có một loại bug silicon mà mô phỏng schematic gần như không bao giờ bắt: chip thi thoảng “lên nhầm” — một thanh ghi cấu hình khởi động ở giá trị rác, một máy trạng thái khoá vào nhánh chết, và lần bật nguồn sau lại bình thường. Bạn soi lại netlist trăm lần, sim tran nào cũng đẹp, vì mọi sim đều bắt đầu ở điểm làm việc DC đã hội tụ với nguồn dựng sẵn 1.8 V. Cái mà sim mặc định bỏ qua chính là quãng đường VDD bò từ 0 lên, và người chịu trách nhiệm cho quãng đó là một khối vài transistor mà không giáo trình analog nào dành cho nó một chương: mạch power-on reset.

Chỗ khó của POR nằm gọn trong một nghịch lý: nó phải ra quyết định đúng khi chính nó còn chưa được cấp đủ nguồn để sống. Mình dựng một con POR ngây thơ trên sky130, mô phỏng bằng ngspice, rồi làm đúng cái việc mà sim thường lười làm — cho VDD dốc lên ở nhiều tốc độ khác nhau. Kết quả là cùng một mạch, có tốc độ dốc nó reset sạch đẹp, có tốc độ dốc nó không hề reset.


Mục lục

  1. POR để làm gì
  2. Nghịch lý bootstrap
  3. Con RC-POR ngây thơ
  4. Bẫy tốc độ dốc nguồn
  5. Brown-out và bài toán re-arm
  6. POR thật làm gì để sống
  7. Tổng kết
  8. Tham khảo

POR để làm gì

Khi bạn cấp nguồn cho một con chip, VDD không nhảy tức thì lên 1.8 V. Nó bò lên theo một cái dốc, nhanh thì vài micro-giây, chậm thì vài chục mili-giây, tuỳ regulator, tuỳ tụ trên board, tuỳ cách bật. Trong suốt quãng dốc đó mọi flip-flop, latch và thanh ghi cấu hình trong chip đang ở trạng thái không xác định: chưa đủ áp để giữ mức logic tin cậy, các nút nội bộ lửng lơ giữa mức cao và thấp.

Nhiệm vụ của POR là phát một tín hiệu reset để giữ toàn chip ở một trạng thái đã biết trong lúc VDD còn thấp, đợi đến khi nguồn đủ cao và các khối chậm như bandgap hay oscillator đã ổn định, rồi nhả reset ra đúng một lần, dứt khoát, không rung. Nghe đơn giản như một cái timer. Cái làm nó khó là điều kiện biên: POR không được đứng ngoài chip mà quan sát, nó nằm trong chip, ăn đúng cái VDD đang-bò-lên mà nó có nhiệm vụ canh chừng.

Nghịch lý bootstrap

Thử nghĩ xem POR có gì để làm việc ở thời điểm VDD = 0.4 V. Chưa có dòng tham chiếu, vì mạch bias cần một điện áp bandgap mà bandgap thì cần được cấp nguồn đủ mới chạy. Chưa có mức logic sạch, vì inverter ở 0.4 V thì ngưỡng chuyển mạch của nó cũng trôi theo. Không có “đất chuẩn” nào ngoài chính cái nguồn đang thay đổi từng micro-giây.

Đây là lý do POR không thể là một comparator gọn gàng so VDD với một mốc cố định — vì cái mốc cố định đó, nếu neo vào bandgap, lại là thứ ra đời muộn hơn cả thời điểm POR cần ra quyết định. Mọi topology POR đều là một câu trả lời khác nhau cho cùng câu hỏi: lấy đâu ra một mốc đáng tin khi chưa có gì đáng tin? Cách rẻ nhất, và cũng là cách để lộ nhiều bẫy nhất, là đừng neo vào điện áp gì cả mà neo vào thời gian — một hằng số RC.

Con RC-POR ngây thơ

Mạch mình dựng đúng như cái mà đa số người vẽ đầu tiên. Một điện trở RR nối từ VDD xuống một nút nội bộ xx, một tụ CC từ xx xuống đất. Nút xx vì thế nạp trễ hơn VDD một hằng số thời gian τ=RC\tau = RC. Đưa xx vào cổng của một inverter CMOS lấy nguồn từ chính VDD, lấy ngõ ra làm tín hiệu por tích cực mức cao: khi xx còn thấp, inverter kéo por lên cao (reset đang được giữ); khi xx nạp vượt ngưỡng chuyển mạch của inverter thì por rơi xuống thấp (nhả reset).

Schematic RC-POR: VDD dốc lên qua R xuống node x, tụ C từ x xuống đất; x lái cổng một inverter CMOS (Mp có bubble, Mn) cấp nguồn từ VDD, ngõ ra por có tụ tải C_por

Ý tưởng là dùng độ trễ RC làm khoảng giữ reset sau khi có nguồn. Trong bản sim mình lấy R=1 MΩR = 1\ \text{M}\Omega, C=100 pFC = 100\ \text{pF}, nên τ=100 μs\tau = 100\ \mu s; inverter là cặp sky130_fd_pr__pfet_01v8/nfet_01v8 với L=0.15 μmL = 0.15\ \mu m, mô phỏng ở corner tt của sky130A. Giá trị RR, CC ở đây là để minh hoạ cơ chế cho rõ — 100 pF trên chip là to phi thực tế, POR thật dùng dòng cỡ nano-amp nạp một tụ nhỏ để kéo dài τ\tau mà không tốn diện tích, nhưng vật lý của cái bẫy sắp thấy thì không đổi.

Viết ra vài quan hệ lý tưởng cho rõ. Nguồn dốc tuyến tính lên mức cuối VF=1.8 VV_F = 1.8\ V trong thời gian TRT_R:

VDD(t)=VFtTR,t<TRV_{DD}(t) = V_F\,\frac{t}{T_R}, \qquad t < T_R

Node xx là đáp ứng của mạch lọc thông thấp RC với đầu vào dốc đó — giải ra được dạng đóng:

vx(t)=VFtTRVFτTR(1et/τ),τ=RCv_x(t) = V_F\,\frac{t}{T_R} - \frac{V_F\,\tau}{T_R}\left(1 - e^{-t/\tau}\right), \qquad \tau = RC

Khi đã qua giai đoạn đầu (tτt \gg \tau), số hạng mũ tắt và xx tụt sau VDD một lượng không đổi, đúng bằng độ dốc nhân hằng số thời gian:

ΔVVDDvx    τdVDDdt=τVFTR\Delta V \equiv V_{DD} - v_x \;\longrightarrow\; \tau\,\frac{dV_{DD}}{dt} = \frac{\tau\,V_F}{T_R}

Chính độ trễ điện áp ΔV\Delta V này là thứ inverter đọc. Ngõ ra por được giữ ở mức cao chừng nào xx còn dưới ngưỡng chuyển mạch VMV_M của inverter — với tỉ lệ wp/wn=2w_p/w_n = 2 mình chọn thì VMVDD/2V_M \approx V_{DD}/2 — và nhả xuống thấp khi xx vượt VMV_M.

Cắm nguồn lên, mọi thứ chạy đúng như hình dung — với một tốc độ dốc nhất định. Vấn đề bắt đầu khi mình đổi tốc độ đó.

Bẫy tốc độ dốc nguồn

Cùng con mạch trên, mình cho VDD dốc từ 0 lên 1.8 V trong hai khoảng thời gian rất khác nhau: 1 µs (nhanh hơn nhiều so với τ\tau) và 10 ms (chậm hơn nhiều so với τ\tau).

Hai panel: trái dốc 1µs, VDD lên gần như tức thì, POR bật cao rồi nhả sau ~66µs; phải dốc 10ms, VDD ramp tuyến tính, POR gần như phẳng ở 0 suốt

Bên trái, dốc nhanh: VDD lên gần như tức thì so với τ\tau, nút xx tụt lại phía sau, nên por được kéo lên đầy đủ và giữ ở đó khoảng 66 µs — cỡ 0.66τ0.66\,\tau — trước khi nhả. Đây đúng là hành vi mong muốn: một xung reset rộng, sạch, đến sau khi nguồn đã tốt. Bên phải, dốc chậm: node xx gần như bám sát VDD trong suốt hành trình (vì τ\tau nhỏ so với thời gian dốc), nên chênh lệch điện áp giữa cổng và nguồn của inverter luôn nhỏ — pfet gần như không bao giờ được bật mạnh để kéo por lên. Kết quả là por gần như phẳng ở 0 từ đầu tới cuối: reset không hề assert. Chip lên nguồn mà không có ai giữ nó ở trạng thái known.

Để thấy đây không phải chuyện “nhanh thì tốt, chậm thì xấu” một cách mơ hồ mà là một cái vách rõ ràng, mình quét thời gian dốc TRT_R từ 1 µs đến 30 ms và đo biên độ đỉnh mà por đạt được, tính theo phần trăm VDD:

Đường cong semilog: biên độ reset giữ 100% khi TR nhỏ hơn RC=100µs, sụp qua vách quanh TR≈RC xuống ~50% ở 300µs, ~24% ở 1ms, và sàn ~7% khi TR≥3ms

Cái vách nằm ngay quanh TRτT_R \approx \tau. Đây chính là hệ quả của độ trễ ΔV=τVF/TR\Delta V = \tau\,V_F/T_R ở mục trước: reset chỉ được kéo lên đủ cao khi ΔV\Delta V đủ lớn để dìm xx xuống dưới VMV_M đúng lúc VDD đã lên cao, tức khi τVF/TRVFVMVF/2\tau V_F/T_R \gtrsim V_F - V_M \approx V_F/2, cho TR2τT_R \lesssim 2\tau — đúng chỗ đường cong bắt đầu rơi. Nhanh hơn RC thì reset đạt gần 100% VDD, chậm hơn RC thì biên độ đổ dốc: còn 51% ở TR=300 μsT_R = 300\ \mu s, 24% ở 1 ms, và từ 3 ms trở đi thì chạm sàn khoảng 7% — tức là thực chất không còn xung reset nào nữa. Điều nguy hiểm là một con POR như thế này qua được mọi bài test nếu bạn chỉ thử nó ở một tốc độ dốc, thường là tốc độ nhanh trên bàn lab. Ra hiện trường, gặp một regulator lên chậm, hoặc một board tụ lớn, nó im lặng thất bại.

Brown-out và bài toán re-arm

Giả sử bạn đã tránh được bẫy trên và POR phát xung reset đàng hoàng lúc bật máy. Vẫn còn một cái bẫy nữa, và nó là chỗ ít được nói tới nhất: chuyện gì xảy ra khi nguồn sụt tạm rồi hồi lại giữa lúc chip đang chạy — một cú brown-out, một glitch trên rail, một lần hot-restart.

Mình cho VDD lên đầy đủ, POR nhả reset xong xuôi, rồi tại 200 µs cho nguồn sụt xuống 0.5 V trong 60 µs rồi hồi về 1.8 V.

VDD lên 1.8V, POR nhả về 0; tại 200µs VDD sụt còn 0.5V trong 60µs; node x chỉ xả tới 1.08V nên POR vẫn nằm ~0, không re-assert reset

Ở 0.5 V thì logic của chip chắc chắn không còn chạy đúng — đây đúng là lúc cần reset để khi hồi nguồn mọi thứ khởi tạo lại. Nhưng nhìn por: nó nằm im ở mức 0 suốt cả cú sụt, không hề re-assert. Thủ phạm là node định thời xx: với τ=100 μs\tau = 100\ \mu s mà cú sụt chỉ 60 µs, tụ CC không kịp xả — xx chỉ tụt từ 1.8 V xuống 1.08 V, vẫn nằm trên ngưỡng chuyển mạch của inverter, nên por không được kéo lên. Chip chui qua brown-out và chạy tiếp từ một trạng thái có thể đã hỏng, không ai reset nó cả.

Đây là bài toán re-arm: sau khi đã phát xong xung reset đầu đời, POR phải được “nạp đạn” lại để lần sụt nguồn sau còn bắn được. Con RC ngây thơ không có cơ chế đó — muốn nó re-arm thì tụ định thời phải xả nhanh khi VDD tụt, mà điện trở nạp lớn thì đúng là không cho phép điều đó.

POR thật làm gì để sống

Nhìn ba cái bẫy trên thì thấy một con POR dùng được ngoài đời không thể chỉ là RC + inverter. Nó thường là sự kết hợp của mấy khối, mỗi khối vá một lỗ:

Phần phát hiện mức áp thay vì chỉ phát hiện độ dốc. Để điểm nhả reset neo vào một điện áp thật (đủ cao để logic chạy đúng ở góc process xấu nhất) chứ không trôi theo tốc độ dốc, người ta so VDD với một ngưỡng. Nhưng để thoát nghịch lý bootstrap, ngưỡng đó thường neo vào VTHV_{TH} của transistor — một chồng diode-connected chẳng hạn — chứ không đợi bandgap. Nhánh RC vẫn giữ, nhưng chỉ để lo giai đoạn cực sớm khi chưa có gì bias nổi, rồi bộ so mức tiếp quản việc quyết định điểm nhả.

Phần chống rung: quanh điểm chuyển, VDD lúc bò lên có nhiễu, nếu không có hysteresis thì por sẽ bật tắt lởm chởm và đẩy cho logic một chuỗi reset răng cưa. Nên bộ so gần như luôn là Schmitt trigger, và tín hiệu nhả phải đơn điệu.

Phần re-arm và brown-out: thêm một đường xả chủ động cho node định thời khi VDD tụt, và thường bắt tay với một mạch brown-out detector riêng — BOD canh VDD trong lúc chạy, thấy nó rơi dưới ngưỡng an toàn thì chủ động kéo reset và reset luôn trạng thái định thời của POR. POR lo lúc lên, BOD lo lúc đang chạy; hai đứa thường đi thành cặp.

Và mấy ràng buộc lặng lẽ bao trùm tất cả: POR chạy mãi mãi, kể cả khi chip ngủ, nên nó phải tiêu thụ cỡ nano-amp — điều này loại thẳng op-amp thường ra khỏi lựa chọn. Điểm trip và độ trễ lại trôi theo process và nhiệt độ, nên ngưỡng nhả phải đặt trên mức VDD tối thiểu mà logic chạy đúng ở góc xấu nhất, nhưng không cao đến mức ở góc khác thì reset kéo dài vô ích. Cân bằng đám ràng buộc mâu thuẫn này, cho một khối chỉ làm việc thật sự có vài trăm nano-giây một lần trong đời con chip, là lý do POR xứng đáng nhiều hơn con số không dòng mà giáo trình dành cho nó.

Tổng kết

POR là ví dụ sạch nhất cho một lớp mạch mà mình muốn viết loạt bài này: không nằm trong signal path, không có chương riêng trong sách, nhưng sai là chip chết. Con RC ngây thơ để lộ ba điều mà chỉ khi cho nguồn dốc lên thật — thay vì bắt đầu sim từ điểm DC dựng sẵn — mới thấy: nó chỉ đúng trong một dải tốc độ dốc, nó im lặng thất bại ngoài dải đó, và nó ngủ quên qua brown-out. Cả ba đều không hiện ra trong một sim tran khởi động từ 1.8 V, mà đó lại là sim mặc định của gần như mọi người.

Nếu có một điều mang về từ bài này, thì là: lần tới khi viết testbench, thử cho VDD của bạn một cái dốc thật — vài tốc độ khác nhau, thêm một cú sụt giữa chừng — và xem con chip của bạn lên như thế nào. Mấy transistor vô hình lo chuyện đó thường là mấy transistor bạn chưa từng nhìn kỹ.

Đây là bài đầu trong một loạt mình tính viết về mấy mạch “hạ tầng” ít được nói tới. Nếu bạn muốn xem thêm mạch khởi động kiểu này, bài bias độc lập nguồn chạm vào đúng bài toán “hai điểm cân bằng và nhánh startup”.

Tham khảo

Các mô phỏng trong bài dựng trên PDK sky130A với mạch RC-POR mô tả ở trên, chạy bằng ngspice qua toolchain mở rootless mà mình mô tả ở phụ lục bộ đồ nghề.1

Footnotes

  1. sky130 PDK và model ngspice: SkyWater sky130 PDK docs. Mô phỏng bằng ngspice.