Files
test-repo/docs/.vitepress/theme/components/appendix/computer-fundamentals/FunctionalUnitDemo.vue
T
2026-02-24 00:18:09 +08:00

370 lines
9.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="functional-unit-demo">
<div class="demo-label">
常见功能单元 切换不同模块查看其实际工作原理
</div>
<div class="tabs">
<button
v-for="tab in tabs"
:key="tab.id"
class="tab-btn"
:class="{ active: currentTab === tab.id }"
@click="currentTab = tab.id"
>
{{ tab.name }}
</button>
</div>
<div class="demo-content">
<!-- MUX Demo -->
<div v-if="currentTab === 'mux'" class="demo-panel">
<div class="panel-desc">
<strong>多路选择器 (MUX)</strong>像铁路道岔一样根据"选择信号"决定让哪一路数据通过
</div>
<div class="mux-container">
<div class="inputs">
<div class="input-line">
<span class="label">数据 0 (D0)</span>
<button
class="toggle-btn"
:class="{ on: muxD0 }"
@click="muxD0 = !muxD0"
>
{{ muxD0 ? '1' : '0' }}
</button>
</div>
<div class="input-line">
<span class="label">数据 1 (D1)</span>
<button
class="toggle-btn"
:class="{ on: muxD1 }"
@click="muxD1 = !muxD1"
>
{{ muxD1 ? '1' : '0' }}
</button>
</div>
</div>
<div class="mux-chip">
<div class="chip-body">MUX</div>
<div class="select-pin">
<span class="label">选择 (Sel)</span>
<button
class="select-btn"
:class="{ on: muxSel }"
@click="muxSel = !muxSel"
>
{{ muxSel ? '1' : '0' }}
</button>
</div>
</div>
<div class="outputs">
<div class="output-line" :class="{ active: muxResult }">
<span class="label">输出 (Out)</span>
<span class="out-val">{{ muxResult ? '1' : '0' }}</span>
</div>
</div>
</div>
<div class="logic-explain">
<p>
当前选择信号为 {{ muxSel ? '1' : '0' }}因此输出等于 数据
{{ muxSel ? '1 (D1)' : '0 (D0)' }} 的值<strong>{{
muxResult ? '1' : '0'
}}</strong>
</p>
</div>
</div>
<!-- Decoder Demo -->
<div v-if="currentTab === 'decoder'" class="demo-panel">
<div class="panel-desc">
<strong>译码器 (Decoder)</strong>将二进制输入转换为特定输出线的激活信号例如 2位输入可以激活
4根输出线中的一根
</div>
<div class="decoder-container">
<div class="inputs vertical">
<div class="input-line">
<button
class="toggle-btn"
:class="{ on: decA1 }"
@click="decA1 = !decA1"
>
{{ decA1 ? '1' : '0' }}
</button>
<span class="label">A1 (高位)</span>
</div>
<div class="input-line">
<button
class="toggle-btn"
:class="{ on: decA0 }"
@click="decA0 = !decA0"
>
{{ decA0 ? '1' : '0' }}
</button>
<span class="label">A0 (低位)</span>
</div>
</div>
<div class="decoder-chip">
<div class="chip-body">2-to-4<br />译码器</div>
</div>
<div class="outputs vertical-out">
<div class="output-line" :class="{ active: decResult === 0 }">
<span class="out-val">{{ decResult === 0 ? '1' : '0' }}</span>
<span class="label">Y0 (当输入 00 )</span>
</div>
<div class="output-line" :class="{ active: decResult === 1 }">
<span class="out-val">{{ decResult === 1 ? '1' : '0' }}</span>
<span class="label">Y1 (当输入 01 )</span>
</div>
<div class="output-line" :class="{ active: decResult === 2 }">
<span class="out-val">{{ decResult === 2 ? '1' : '0' }}</span>
<span class="label">Y2 (当输入 10 )</span>
</div>
<div class="output-line" :class="{ active: decResult === 3 }">
<span class="out-val">{{ decResult === 3 ? '1' : '0' }}</span>
<span class="label">Y3 (当输入 11 )</span>
</div>
</div>
</div>
<div class="logic-explain">
<p>
当前输入为二进制的 {{ decA1 ? '1' : '0'
}}{{ decA0 ? '1' : '0' }} (十进制 {{ decResult }})因此只有
<strong>Y{{ decResult }}</strong> 被激活输出 1
</p>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const tabs = [
{ id: 'mux', name: '多路选择器 (MUX)' },
{ id: 'decoder', name: '译码器 (Decoder)' }
]
const currentTab = ref('mux')
// MUX State
const muxD0 = ref(false)
const muxD1 = ref(true)
const muxSel = ref(false)
const muxResult = computed(() => (muxSel.value ? muxD1.value : muxD0.value))
// Decoder State
const decA1 = ref(false)
const decA0 = ref(false)
const decResult = computed(() => (decA1.value ? 2 : 0) + (decA0.value ? 1 : 0))
</script>
<style scoped>
.functional-unit-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem 1.2rem;
margin: 1rem 0;
}
.demo-label {
font-size: 0.78rem;
font-weight: bold;
color: var(--vp-c-text-2);
margin-bottom: 0.75rem;
letter-spacing: 0.2px;
}
.tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
border-bottom: 1px solid var(--vp-c-divider);
padding-bottom: 0.5rem;
}
.tab-btn {
padding: 0.4rem 0.8rem;
font-size: 0.85rem;
border-radius: 4px;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
color: var(--vp-c-text-2);
cursor: pointer;
transition: all 0.2s;
}
.tab-btn:hover {
border-color: var(--vp-c-brand-1);
}
.tab-btn.active {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand-1);
border-color: var(--vp-c-brand-1);
font-weight: bold;
}
.panel-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-bottom: 1rem;
}
/* common elements */
.toggle-btn {
width: 2rem;
height: 2rem;
border-radius: 4px;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
font-weight: bold;
font-family: monospace;
cursor: pointer;
transition: all 0.2s;
}
.toggle-btn.on {
background: var(--vp-c-green-soft, #dcfce7);
color: var(--vp-c-green-1, #16a34a);
border-color: var(--vp-c-green-1, #16a34a);
}
.out-val {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
border-radius: 4px;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
font-weight: bold;
font-family: monospace;
}
.output-line.active .out-val {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand-1);
border-color: var(--vp-c-brand-1);
}
.output-line.active .label {
color: var(--vp-c-brand-1);
font-weight: bold;
}
.logic-explain {
margin-top: 1rem;
padding: 0.8rem;
background: var(--vp-c-bg);
border-radius: 6px;
font-size: 0.85rem;
text-align: center;
color: var(--vp-c-text-2);
}
/* MUX Layout */
.mux-container {
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
padding: 1rem;
}
.inputs {
display: flex;
flex-direction: column;
gap: 1rem;
}
.input-line {
display: flex;
align-items: center;
gap: 0.5rem;
}
.label {
font-size: 0.8rem;
color: var(--vp-c-text-3);
font-variant-numeric: tabular-nums;
}
.mux-chip {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.chip-body {
width: 4rem;
height: 6rem;
background: var(--vp-c-bg-alt);
border: 2px solid var(--vp-c-divider);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
clip-path: polygon(0 0, 100% 20%, 100% 80%, 0 100%);
}
.select-pin {
position: absolute;
bottom: -2.5rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.3rem;
}
.select-btn {
width: 2rem;
height: 1.5rem;
border-radius: 4px;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
font-size: 0.8rem;
cursor: pointer;
}
.select-btn.on {
background: #fef08a; /* yellow soft */
color: #a16207;
border-color: #a16207;
}
/* Decoder Layout */
.decoder-container {
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
padding: 1rem;
}
.inputs.vertical,
.outputs.vertical-out {
display: flex;
flex-direction: column;
gap: 0.8rem;
}
.decoder-chip .chip-body {
width: 5rem;
height: 8rem;
background: var(--vp-c-bg-alt);
border: 2px solid var(--vp-c-divider);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
text-align: center;
clip-path: none;
border-radius: 4px;
}
</style>