Show description
Lab 1 Guide • Half Adder → Full Adder → 4‑bit Incrementer/Adder • Digital + Verilog + GTKWave
Lab 1 Guide • Half Adder → Full Adder → 4‑bit Incrementer/Adder • Digital + Verilog + GTKWave
Lab 1 — Half Adder • Full Adder • 4‑bit Incrementer • 4‑bit Adder
dark‑ASCII pro guide
Overview
Files & Roles
Toolchain
Task 1‑1
Task 1‑2
Task 1‑3
Task 1‑4
Testing & Stimulus
Pitfalls
Zip Checklist
Video Script
FAQ
Overview
This one‑pager is a complete walkthrough for building, exporting, simulating, and verifying the Lab 1 circuits in Digital → Verilog → GTKWave. It covers the logic (half/full adders), bus wiring with splitters/mergers, the role of *_top.v test benches, stimulus text files, iVerilog commands, wave inspection, edge‑case tests (signed/unsigned overflow), and a ready‑to‑use video script. Dark ASCII vibes included.
Quick win: Keep all files inside a single Lab1/ folder. Digital subcircuits must be discoverable from the current project directory; saving early avoids the “custom component not visible” gotcha.
File Types & What They Do
*.dig — Your Digital schematics (source of truth for the logic).
*.v — Verilog exports of your schematics (your DUT: Design‑Under‑Test).
*_top.v — Test benches that instantiate your DUT, feed inputs, and check outputs.
*_stim.txt — Stimulus/expected values consumed by the test benches.
*_waves.vcd — Waveform dumps for GTKWave visualization.
Directory Layout (recommended)
Lab1/
Lab1/
├─ half_adder.dig
├─ half_adder.v
├─ half_adder_top.v
├─ half_adder_stim.txt
│
├─ incrementer.dig
├─ incrementer.v
├─ incrementer_top.v
│
├─ full_adder.dig
├─ full_adder.v
├─ full_adder_top.v
├─ full_adder_stim.txt
│
├─ four_bit_adder.dig
├─ four_bit_adder.v
├─ four_bit_adder_top.v
├─ four_bit_adder_stim.txt
│
├─ screenshots/ (optional)
└─ my_answers.pdf (report)
Include the *_top.v and *_stim.txt files in your zip so the grader can re‑run your sims 1:1.
Toolchain & Commands
iVerilog Build + Run
Copyiverilog -o half_adder.exe half_adder.v half_adder_top.v
./half_adder.exe # Windows: vvp half_adder.exe
iverilog -o incrementer.exe incrementer.v incrementer_top.v
./incrementer.exe
iverilog -o full_adder.exe full_adder.v full_adder_top.v
./full_adder.exe
iverilog -o four_bit_adder.exe four_bit_adder.v four_bit_adder_top.v
./four_bit_adder.exe
GTKWave
Copygtkwave half_adder_waves.vcd
# or: …
Lab 1 Guide • Half Adder → Full Adder → 4‑bit Incrementer/Adder • Digital + Verilog + GTKWave
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Lab 1 Guide • Half Adder → Full Adder → 4‑bit Incrementer/Adder • Digital + Verilog + GTKWave</title>
<style>
:root{
--bg:#0a0b0f; /* abyss */
--panel:#0f1117; /* deep slate */
--muted:#8a8f98; /* iron */
--text:#dfe7ef; /* ice */
--accent:#7efcf6; /* neon cyan */
--accent2:#c084fc; /* neon violet */
--ok:#a7f3d0; /* mint */
--warn:#fde68a; /* gold */
--bad:#fca5a5; /* soft red */
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
font: 16px/1.6 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
color:var(--text);
background:radial-gradient(1200px 1200px at 80% -20%, #18202c 0%, #0c0f15 40%, var(--bg) 70% 100%);
overflow-x:hidden;
}
/* ASCII matrix rain background */
canvas#asciiRain{position:fixed;inset:0;z-index:-2;filter:opacity(.14) contrast(120%)}
/* Subtle scanline */
.scanline{position:fixed;inset:0;background:repeating-linear-gradient( to bottom, rgba(255,255,255,.02) 0 2px, transparent 2px 4px );mix-blend-mode:soft-light;pointer-events:none;z-index:-1}
a{color:var(--accent);text-decoration:none}
a:hover{color:#b0fff9;text-shadow:0 0 6px #67fff5}
.container{max-width:1100px;margin:0 auto;padding:28px}
header{
position:sticky;top:0;z-index:5;
background:linear-gradient(180deg, rgba(15,17,23,.92), rgba(15,17,23,.65));
backdrop-filter: blur(6px);
border-bottom:1px solid rgba(126,252,246,.15);
}
.title{
display:flex;gap:18px;align-items:center;justify-content:space-between;flex-wrap:wrap
}
.title h1{margin:10px 0;font-size: clamp(20px, 3.2vw, 34px);letter-spacing:.5px}
.chip{border:1px solid rgba(126,252,246,.25);padding:6px 10px;border-radius:10px;color:var(--accent);background:rgba(126,252,246,.08)}
nav.toc{margin:18px 0 8px;display:flex;flex-wrap:wrap;gap:10px}
nav.toc a{padding:6px 10px;border:1px solid rgba(192,132,252,.2);border-radius:8px;color:var(--accent2);background:rgba(192,132,252,.08)}
section{margin:28px 0;padding:22px;background:linear-gradient(180deg, rgba(18,20,28,.8), rgba(10,12,18,.7));border:1px solid rgba(126,252,246,.12);border-radius:16px;box-shadow:0 0 0 1px rgba(126,252,246,.04) inset, 0 20px 60px rgba(0,0,0,.35)}
section h2{margin-top:0;font-size: clamp(18px, 2.4vw, 26px)}
h3{margin:18px 0 8px;font-size: clamp(16px, 2vw, 22px)}
p{margin:8px 0;color:#dfebff}
.subtle{color:var(--muted)}
.grid{display:grid;gap:16px}
@media(min-width:900px){.grid.cols-2{grid-template-columns:1fr 1fr}}
.card{padding:16px;border:1px solid rgba(126,252,246,.12);background:rgba(12,16,22,.6);border-radius:12px}
pre,code{font: 13.5px/1.5 ui-monospace,Consolas,Menlo,monospace}
pre{position:relative;background:#0c1118;border:1px solid rgba(126,252,246,.2);padding:14px 14px 16px;border-radius:12px;overflow:auto}
pre .copy{position:absolute;top:8px;right:8px;font-size:12px;padding:4px 8px;border:1px solid rgba(126,252,246,.35);border-radius:8px;background:rgba(126,252,246,.08);color:var(--accent);cursor:pointer}
code.inline{padding:2px 6px;background:#0c1118;border:1px solid rgba(126,252,246,.2);border-radius:6px}
.kbd{display:inline-block;padding:2px 6px;margin:0 2px;border:1px solid rgba(223,231,239,.25);border-bottom-width:3px;border-radius:6px;background:rgba(255,255,255,.04)}
.callout{border-left:3px solid var(--accent);padding:12px 14px;background:linear-gradient(90deg, rgba(126,252,246,.08), transparent);border-radius:8px}
.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}
.ascii-box{border:1px solid rgba(126,252,246,.2);border-radius:12px;overflow:hidden}
.ascii-head{background:linear-gradient(180deg, rgba(126,252,246,.12), rgba(126,252,246,.04));padding:10px 12px;color:var(--accent)}
.ascii-body{padding:12px;font-size:13.5px;white-space:pre;overflow:auto;color:#9dd9d6}
footer{padding:32px 0;color:var(--muted);text-align:center}
.glow{box-shadow:0 0 20px rgba(126,252,246,.18)}
.pulse{animation:pulse 2.2s infinite}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(126,252,246,.22)}50%{box-shadow:0 0 0 10px rgba(126,252,246,0)}}
.badge{display:inline-flex;gap:8px;align-items:center}
.badge .dot{width:8px;height:8px;background:var(--accent);border-radius:999px;box-shadow:0 0 8px var(--accent)}
.small{font-size:12.5px}
.table{width:100%;border-collapse:separate;border-spacing:0}
.table th,.table td{border-bottom:1px dashed rgba(126,252,246,.18);padding:10px 8px;text-align:left}
.table th{color:#b9f8f4}
</style>
</head>
<body>
<canvas id="asciiRain"></canvas>
<div class="scanline"></div>
<header>
<div class="container title">
<h1>Lab 1 — Half Adder • Full Adder • 4‑bit Incrementer • 4‑bit Adder</h1>
<div class="badge chip"><span class="dot"></span> dark‑ASCII pro guide</div>
</div>
<div class="container">
<nav class="toc">
<a href="#overview">Overview</a>
<a href="#files">Files & Roles</a>
<a href="#toolchain">Toolchain</a>
<a href="#task11">Task 1‑1</a>
<a href="#task12">Task 1‑2</a>
<a href="#task13">Task 1‑3</a>
<a href="#task14">Task 1‑4</a>
<a href="#testing">Testing & Stimulus</a>
<a href="#pitfalls">Pitfalls</a>
<a href="#zip">Zip Checklist</a>
<a href="#video">Video Script</a>
<a href="#faq">FAQ</a>
</nav>
</div>
</header>
<main class="container">
<section id="overview" class="glow">
<h2>Overview</h2>
<p>This one‑pager is a complete walkthrough for building, exporting, simulating, and verifying the Lab 1 circuits in <span class="chip">Digital → Verilog → GTKWave</span>. It covers the logic (half/full adders), bus wiring with splitters/mergers, the role of <code class="inline">*_top.v</code> test benches, stimulus text files, iVerilog commands, wave inspection, edge‑case tests (signed/unsigned overflow), and a ready‑to‑use video script. Dark ASCII vibes included.</p>
<div class="callout small"><strong>Quick win:</strong> Keep all files inside a single <code class="inline">Lab1/</code> folder. Digital subcircuits must be discoverable from the current project directory; saving early avoids the “custom component not visible” gotcha.</div>
</section>
<section id="files" class="grid cols-2">
<div class="card">
<h3>File Types & What They Do</h3>
<ul>
<li><code class="inline">*.dig</code> — Your Digital schematics (source of truth for the logic).</li>
<li><code class="inline">*.v</code> — Verilog exports of your schematics (your DUT: Design‑Under‑Test).</li>
<li><code class="inline">*_top.v</code> — Test benches that instantiate your DUT, feed inputs, and check outputs.</li>
<li><code class="inline">*_stim.txt</code> — Stimulus/expected values consumed by the test benches.</li>
<li><code class="inline">*_waves.vcd</code> — Waveform dumps for GTKWave visualization.</li>
</ul>
</div>
<div class="card">
<h3>Directory Layout (recommended)</h3>
<div class="ascii-box">
<div class="ascii-head">Lab1/</div>
<div class="ascii-body">Lab1/
├─ half_adder.dig
├─ half_adder.v
├─ half_adder_top.v
├─ half_adder_stim.txt
│
├─ incrementer.dig
├─ incrementer.v
├─ incrementer_top.v
│
├─ full_adder.dig
├─ full_adder.v
├─ full_adder_top.v
├─ full_adder_stim.txt
│
├─ four_bit_adder.dig
├─ four_bit_adder.v
├─ four_bit_adder_top.v
├─ four_bit_adder_stim.txt
│
├─ screenshots/ (optional)
└─ my_answers.pdf (report)</div>
</div>
<p class="small subtle">Include the <code class="inline">*_top.v</code> and <code class="inline">*_stim.txt</code> files in your zip so the grader can re‑run your sims 1:1.</p>
</div>
</section>
<section id="toolchain">
<h2>Toolchain & Commands</h2>
<div class="grid cols-2">
<div class="card">
<h3>iVerilog Build + Run</h3>
<pre><button class="copy" data-copy="iverilog -o half_adder.exe half_adder.v half_adder_top.v\n./half_adder.exe">Copy</button>iverilog -o half_adder.exe half_adder.v half_adder_top.v
./half_adder.exe # Windows: vvp half_adder.exe
iverilog -o incrementer.exe incrementer.v incrementer_top.v
./incrementer.exe
iverilog -o full_adder.exe full_adder.v full_adder_top.v
./full_adder.exe
iverilog -o four_bit_adder.exe four_bit_adder.v four_bit_adder_top.v
./four_bit_adder.exe</pre>
</div>
<div class="card">
<h3>GTKWave</h3>
<pre><button class="copy" data-copy="gtkwave half_adder_waves.vcd">Copy</button>gtkwave half_adder_waves.vcd
# or: open GTKWave app → File → Open New Tab → select *_waves.vcd</pre>
<p class="small subtle">Pro tip: expand the top‑level module, add only DUT I/Os (e.g., <code class="inline">a, b, cin, sum, cout, y, cry, overfl</code>) to keep waves clean.</p>
</div>
</div>
</section>
<section id="task11">
<h2>Task 1‑1 • 1‑Bit Half Adder</h2>
<div class="grid cols-2">
<div class="card">
<h3>Logic</h3>
<p><strong>sum =</strong> A ⊕ B, <strong>cry =</strong> A · B</p>
<table class="table small">
<thead><tr><th>A</th><th>B</th><th>cry</th><th>sum</th></tr></thead>
<tbody>
<tr><td>0</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>0</td><td>1</td><td>0</td><td>1</td></tr>
<tr><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>1</td><td>1</td><td>1</td><td>0</td></tr>
</tbody>
</table>
</div>
<div class="card">
<h3>Export & Sim</h3>
<ol class="small">
<li>Save schematic as <code class="inline">half_adder.dig</code>.</li>
<li>Export Verilog → <code class="inline">half_adder.v</code>.</li>
<li>Run iVerilog with <code class="inline">half_adder_top.v</code> and open <code class="inline">half_adder_waves.vcd</code>.</li>
</ol>
<div class="callout small">If GTKWave shows mismatches, re‑check pin names <em>exactly</em> (e.g., <code class="inline">cry</code> vs <code class="inline">carry</code>).</div>
</div>
</div>
</section>
<section id="task12">
<h2>Task 1‑2 • 4‑Bit Incrementer</h2>
<div class="grid cols-2">
<div class="card">
<h3>Design</h3>
<p>Build from four half adders. Use splitters/mergers for 4‑bit <code class="inline">a</code> → <code class="inline">y</code>, controlled by <code class="inline">inc</code>. When <code class="inline">inc=0</code>, pass‑through; when <code class="inline">inc=1</code>, add 1 (propagate carries).</p>
</div>
<div class="card">
<h3>Sim Check</h3>
<ul class="small">
<li>For <code class="inline">a=0x5, inc=0</code> ⇒ <code class="inline">y=0x5</code>, <code class="inline">cry=0</code>.</li>
<li>For <code class="inline">a=0xF, inc=1</code> ⇒ <code class="inline">y=0x0</code>, <code class="inline">cry=1</code>.</li>
</ul>
</div>
</div>
</section>
<section id="task13">
<h2>Task 1‑3 • 1‑Bit Full Adder</h2>
<div class="grid cols-2">
<div class="card">
<h3>Logic</h3>
<p><strong>sum =</strong> A ⊕ B ⊕ Cin</p>
<p><strong>cout =</strong> majority(A,B,Cin) = A·B + A·Cin + B·Cin</p>
<p class="small subtle">Digital hint: set XOR and OR to 3 inputs in properties.</p>
</div>
<div class="card">
<h3>Stim Bits (full_adder_stim.txt)</h3>
<div class="small">Bit map: <code class="inline">[7:6 unused][5 cout][4 sum][3 unused][2 cin][1 a][0 b]</code></div>
</div>
</div>
</section>
<section id="task14">
<h2>Task 1‑4 • 4‑Bit Full Adder</h2>
<div class="grid cols-2">
<div class="card">
<h3>Design</h3>
<p>Cascade four 1‑bit full adders, split/merge 4‑bit buses for <code class="inline">a</code> and <code class="inline">b</code>. Outputs: <code class="inline">y[3:0]</code>, <code class="inline">cout</code> (unsigned carry out), <code class="inline">overfl</code> (signed overflow).</p>
<div class="callout small"><strong>Signed vs Unsigned:</strong> 4‑bit unsigned is 0..15; two’s‑complement signed is −8..+7. Hardware is identical; interpretation changes how you read <code class="inline">cout</code> vs <code class="inline">overfl</code>.</div>
</div>
<div class="card">
<h3>Classic Edge Cases</h3>
<ul class="small">
<li><em>Unsigned overflow</em>: F + 1 → <code class="inline">cout=1</code></li>
<li><em>Signed overflow (+ + → −)</em>: 7 + 4 → overflows (positive + positive yields negative)</li>
<li><em>Signed overflow (− − → +)</em>: (8) + (8) → overflows (negative + negative yields positive)</li>
</ul>
</div>
</div>
</section>
<section id="testing">
<h2>Testing & Stimulus Files</h2>
<div class="grid cols-2">
<div class="card">
<h3>four_bit_adder_stim.txt bit map</h3>
<div class="small">Bit layout per hex nibble (20 bits total):</div>
<div class="ascii-box">
<div class="ascii-head">[19:0] mapping</div>
<div class="ascii-body">[19:18 unused] [17 exp_overfl] [16 exp_cout] [15:12 exp_y3..0] [11:9 unused] [8 cin] [7:4 a3..0] [3:0 b3..0]</div>
</div>
<p class="small subtle">Each row like <code class="inline">E_0_F_F_?</code> is five hex digits separated by underscores for readability.</p>
</div>
<div class="card">
<h3>Example Test Rows & Motives</h3>
<table class="table small">
<thead><tr><th>Stimulus</th><th>What it checks</th></tr></thead>
<tbody>
<tr><td><code class="inline">0_0_0_0_0</code></td><td>Stuck‑at‑1 sanity (no wires tied high)</td></tr>
<tr><td><code class="inline">0_3_0_1_2</code></td><td>Simple add: 1 + 2 → y=3</td></tr>
<tr><td><code class="inline">0_4_1_1_2</code></td><td>Carry‑in handling</td></tr>
<tr><td><code class="inline">0_F_0_F_0</code></td><td>Max + 0</td></tr>
<tr><td><code class="inline">1_0_0_F_1</code></td><td>Smallest unsigned overflow</td></tr>
<tr><td><code class="inline">3_2_0_9_9</code></td><td>Signed overflow (−7 + −7)</td></tr>
<tr><td><code class="inline">2_8_0_7_1</code></td><td>Smallest signed overflow (+7 + +1)</td></tr>
<tr><td><code class="inline">2_9_1_4_4</code></td><td>Signed overflow with Cin (4 + 4 + 1)</td></tr>
</tbody>
</table>
</div>
</div>
<div class="card">
<h3>Stim Harness Pattern</h3>
<pre><button class="copy" data-copy="iverilog -o four_bit_adder.exe four_bit_adder.v four_bit_adder_top.v\n./four_bit_adder.exe\n# If a mismatch appears, the printed index lines up with your test row number (0..15).">Copy</button>iverilog -o four_bit_adder.exe four_bit_adder.v four_bit_adder_top.v
./four_bit_adder.exe
# If a mismatch appears, the printed index lines up with your test row number (0..15).</pre>
</div>
</section>
<section id="pitfalls" class="grid cols-2">
<div class="card">
<h3>Common Pitfalls</h3>
<ul class="small">
<li><strong>Wrong signal names:</strong> Use <code class="inline">cry</code> (not <em>carry</em>) where required.</li>
<li><strong>Custom component not visible:</strong> Save a new schematic into <code class="inline">Lab1/</code> first so <code class="inline">Components → Custom</code> refreshes.</li>
<li><strong>Splitter order:</strong> Put MSB on top (<code class="inline">[3..0]</code>) consistently for readability.</li>
<li><strong>Overfl vs cout:</strong> Know which flag means signed vs unsigned overflow.</li>
</ul>
</div>
<div class="card">
<h3>Quick Sanity Matrix</h3>
<table class="table small">
<thead><tr><th>Case</th><th>Inputs</th><th>Expect</th></tr></thead>
<tbody>
<tr><td>Increment wrap</td><td>a=F, inc=1</td><td>y=0, cry=1</td></tr>
<tr><td>Unsigned carry</td><td>a=F, b=1, cin=0</td><td>cout=1</td></tr>
<tr><td>Signed overflow (+ +)</td><td>a=7, b=4, cin=0</td><td>overfl=1</td></tr>
<tr><td>Signed overflow (− −)</td><td>a=8, b=8, cin=0</td><td>overfl=1</td></tr>
</tbody>
</table>
</div>
</section>
<section id="zip">
<h2>Submission Zip Checklist</h2>
<ul class="small">
<li>All <code class="inline">*.dig</code> schematics</li>
<li>All exported <code class="inline">*.v</code> DUT files</li>
<li>All provided <code class="inline">*_top.v</code> test benches</li>
<li>All provided/edited <code class="inline">*_stim.txt</code> files</li>
<li><code class="inline">*_waves.vcd</code> optional but helpful</li>
<li>Screenshot images (schematics + waves)</li>
<li><code class="inline">my_answers.pdf</code> (completed template)</li>
</ul>
<div class="callout">Do <em>not</em> embed your video in the zip. Host it and include the link in your PDF.</div>
</section>
<section id="video">
<h2>Fast Video Script (teleprompter‑ready)</h2>
<div class="card">
<ol class="small">
<li><strong>Intro (10–15s):</strong> “Hi, I’m Lalo Morales — Lab 1: Half Adder, Full Adder, 4‑bit Incrementer/Adder. I’ll show schematics and GTKWave results.”</li>
<li><strong>Half Adder (~20s):</strong> Show XOR/AND, truth table match in waves.</li>
<li><strong>Incrementer (~20s):</strong> Four half adders + splitters. <code class="inline">inc=0</code> pass‑through, <code class="inline">inc=1</code> +1, wrap at F→0 with <code class="inline">cry=1</code>.</li>
<li><strong>Full Adder (~20s):</strong> 3‑input XOR/OR, sum & carry logic demo.</li>
<li><strong>4‑bit Adder (~30–40s):</strong> Cascaded full adders, signed vs unsigned flags, edge‑case tests all pass.</li>
<li><strong>Close (10–15s):</strong> “All circuits verified. Thanks!”</li>
</ol>
</div>
</section>
<section id="faq" class="grid cols-2">
<div class="card">
<h3>FAQ — Why include <code class="inline">*_top.v</code>?</h3>
<p>They’re the test benches. They instantiate your DUT, feed vectors from <code class="inline">*_stim.txt</code>, and auto‑check expected outputs. Without them, the grader can’t re‑run your sims.</p>
</div>
<div class="card">
<h3>GTKWave looks noisy — what do I add?</h3>
<p>Add only high‑level I/Os: <code class="inline">a, b, cin, y, cout, overfl, inc, cry</code>. Ignore internal <code class="inline">s#</code> wires unless debugging.</p>
</div>
</section>
<footer>
<div class="small">© Lab 1 Reference • Single‑file HTML • Dark ASCII theme • Built for speed and clarity</div>
</footer>
</main>
<script>
// Matrix ASCII rain — adapted for subtle ambience
const canvas = document.getElementById('asciiRain');
const ctx = canvas.getContext('2d');
const glyphs = "░▒▓#*+:-·".split("");
let w, h, cols, drops;
function resize(){
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
cols = Math.floor(w / 12);
drops = Array(cols).fill(0).map(()=> Math.random()*h);
}
window.addEventListener('resize', resize); resize();
function tick(){
ctx.fillStyle = 'rgba(10,11,15,0.22)';
ctx.fillRect(0,0,w,h);
ctx.fillStyle = 'rgba(126,252,246,0.35)';
ctx.font = '12px ui-monospace,Consolas,Menlo,monospace';
for(let i=0;i<cols;i++){
const ch = glyphs[(Math.random()*glyphs.length)|0];
ctx.fillText(ch, i*12, drops[i]);
drops[i] += 14 + Math.random()*6;
if(drops[i] > h) drops[i] = -Math.random()*200;
}
requestAnimationFrame(tick);
}
tick();
// Smooth scroll for TOC
document.querySelectorAll('nav.toc a').forEach(a=>{
a.addEventListener('click', e=>{e.preventDefault(); document.querySelector(a.getAttribute('href')).scrollIntoView({behavior:'smooth',block:'start'});});
});
// Copy buttons
document.querySelectorAll('pre .copy').forEach(btn=>{
btn.addEventListener('click',async()=>{
const text = btn.getAttribute('data-copy');
try{ await navigator.clipboard.writeText(text); btn.textContent='Copied'; setTimeout(()=>btn.textContent='Copy',1200);}catch{ btn.textContent='Copy failed'; setTimeout(()=>btn.textContent='Copy',1200);}
});
});
</script>
</body>
</html>