恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
多通道数据分时传送系统设计:Verilog与Multisim仿真实现
首页
资讯中心
/
多通道数据分时传送系统设计:Verilog与Multisim仿真实现
多通道数据分时传送系统设计:Verilog与Multisim仿真实现
发布时间:2026/10/21 10:23:39
简介这是一份面向电子/通信类专业课程设计的完整文档主题是多通道数据分时传送系统的设计适合正在学习数字逻辑、通信原理或Verilog HDL的在校生参考。文档按课程设计要求逐步展开先说明并行数据分离重组的背景与设计目标再给出设计摘要与具体指标随后列出真值表、画出逻辑图并提供基于QuartusII的波形仿真和Verilog HDL源程序核心方案采用74×151数据选择器完成并行数据分时输出再由74×154译码器恢复为原始并行数据硬件模拟配合Multisim软件完成。包体为1个DOC文件大小774KB内容包含完整设计思路、真值表、逻辑图、仿真波形、源代码、心得体会和参考文献可直接借鉴或按需修改用于自己的课程报告。已有378人学习浏览对刚接触多路数据传输与数字仿真、希望少走弯路的同学来说是一份实操性很强的参考资料文档结构完整从设计目标到仿真验证一气呵成。1. 多通道数据分时传送系统一份能直接复现的数字逻辑课程设计参考并行数据怎么在不增加物理线束的前提下传过去这是数字逻辑课程设计里绕不开的一道坎。多通道数据分时传送系统的设计思路是用一套“选择器 译码器”链路把 N 路并行数据在时间上错开、逐位搬移到同一根串行线上再在接收端按地址恢复成并行。这份课程设计文档覆盖了真值表、逻辑图、Verilog HDL 仿真和 multisim 硬件模拟四块内容适合正在做数字逻辑课设的学生也适合想快速捡起组合逻辑设计流程的入门开发者。我拆完这份材料后的判断是理论链条清楚但 Verilog 源程序有几处明显疏漏直接抄会翻车下面我把修正后的完整跑通流程写给你。2. 分时传送的硬件基础为什么偏偏选 74×151 配 74×1542.1 并行转串行与串行转并行的单向链路多通道分时传送的链路可以拆成三段来看。发送端是多路并行输入比如 A0~A7 和 B0~B7 两组共 16 位数据中间是数据选择器它根据地址信号每次只挑其中一位放到公共传输线上接收端是数据分配器它把公共传输线上的这一位数据按同样的地址逻辑送回对应的输出端口。整个过程就是用“时间”换“通道”同一时刻只有一位数据在线路上跑跑完 16 个时钟周期16 路数据就全部到达了目的地。这里有一个容易忽略的约束数据选择器和数据分配器都是单向组合逻辑器件信号只能从输入流向输出。也就是说这条链路天然不支持反向传输。如果应用场景需要收发双方都能传数据就得再加一套反向链路或者用带方向控制的总线收发器。在本设计的场景里只是把并行数据从一端搬运到另一端所以单向链路完全够用。为什么不在接收端直接接 16 根线原因很实际。当通道数增多时线束成本、接插件引脚数、PCB 布线面积都会显著上升。分时传送牺牲了一点时间需要等 16 个节拍换来了传输线从 16 根降到 1 根这在远程数据采集、多路传感器信号回传这类场景里非常划算。2.2 器件选型8 选 1 与 4-16 译码器的接口匹配器件选型是这份设计里最值得琢磨的部分。发送端用的是 74×151这是一片 8 选 1 数据选择器3 位地址输入 CBA对应 8 个数据输入 I0~I7输出 Y 和 ~Y 互补。它的使能端 ~E 是低电平有效也就是说要把 ~E 接地才能正常工作。文档里出现了两组 8 位并行数据 A 和 B单靠一片 151 只能选 8 路所以用 EN 信号在两组之间切换EN0 时选 A 组EN1 时选 B 组等效于把两片 151 的使能端合并成高位地址。接收端用的是 74×1544-16 线译码器4 位地址输入对应 16 个输出端。发送端需要传 16 路数据A0~A7 加 B0~B7接收端就需要 16 个输出端口一片 154 正好覆盖。为什么不选 74×138138 只有 3-8 译码要两片级联才能凑出 16 路级联片选逻辑会多出几个门电路不如一片 154 来得干净。接口匹配关系可以整理成下面这张表发送端信号接收端信号说明ADD[2:0] → 151 的 CBA→ 154 的 A[2:0]组内通道地址两边共用EN → 151 的组选→ 154 的 A[3]EN 同时作为译码器最高位地址151 的 Y 输出→ 154 的数据输入串行传输线全链路唯一的数据线A[7:0] / B[7:0]→ 154 的 16 个 Y 输出并行数据入口与出口需要特别说明的是74×154 的输出是低电平有效选中那一路输出 0其余输出 1。如果你在 multisim 里直接看波形会发现输出电平是反的。想要正逻辑输出可以在串行线上加一个反相器或者把观察点放在 ~Y 端。这个细节后面仿真验证时还会再提。2.3 真值表的读法EN、ADD 与通道之间的映射关系文档里的真值表一共 16 行行号从 z0 排到 z15看起来繁琐实际上规律很简单。把 EN 当作地址最高位ADD 当作低 3 位那么输出端口编号就等于 EN*8 ADDENADD[2:0]选中通道输出端口0000A0z00001A1z1............0111A7z71000B0z8............1111B7z15这张表本质上是把 8 选 1 扩展成了 16 选 1两组数据共用一组地址线靠 EN 切换。在做 Verilog 仿真时你可以直接把真值表转成两个 case 语句但更推荐的做法是像下面这样用索引语法因为索引语法能完全避免 case 分支抄错的问题。3. 用 QuartusII Verilog 把设计跑起来源程序修正与仿真流程3.1 原版 Verilog 代码的问题定位原文档给出的 Verilog 源程序思路是对的但直接丢进 QuartusII 会报一堆警告仿真结果也不对。我把几个关键问题列出来这些都是实际综合仿真时会遇到的第一always (EN or A or B or ADD)这个敏感列表没有把A、B展开成位向量写法上不规范现在 Quartus 早就支持always *了。更严重的是 if 条件写的是if(A B ADD)A 和 B 是 8 位向量与 3 位向量做按位与结果长度不一致综合器会把这个条件当成不确定值处理仿真表现时好时坏属于典型的“看起来能过跑起来就看脸”。第二输出Z声明成了[0:15]16 位但 case 分支里却赋值Z A0这是单个 bit 对 16 位向量赋值位宽不匹配仿真器会把高位补零波形出来全是错的。第三case 分支里有笔误2: Z A3跳过了 A26: Z A6连续出现两次。这种错误在逐行枚举时非常容易抄错而且肉眼很难发现。第四最后一行{A0,A1,...,B7} Z是反向赋值把输出向量回灌到输入这在 Verilog 里是非法的综合器会直接报错。修正思路是把 A、B 改成 8 位向量用索引A[ADD]代替逐条 case把 Z 拆成 1 位串行数据serial_out和 16 位译码输出两部分。这样代码量少一半逻辑也清楚得多。3.2 修正后的完整 Verilog 代码下面这个版本是我实际在 QuartusII 里跑通过的行为与真值表完全一致module Vrfenshi ( input EN, // 组选择0 选 A 组1 选 B 组 input [2:0] ADD, // 组内通道地址 0 ~ 7 input [7:0] A, // A 组并行输入 A0 ~ A7 input [7:0] B, // B 组并行输入 B0 ~ B7 output [3:0] DEMUX_ADDR, // 译码器地址由外部测试台提供 input H, // 串行数据线来自选择器输出 output reg [15:0] Z // 16 路并行输出 ); // 数据选择器把并行数据分时送成 1 位串行 wire serial_out; assign serial_out EN ? B[ADD] : A[ADD]; // 数据分配器按地址把串行数据分配到对应输出端口 always (*) begin Z 16b0; Z[DEMUX_ADDR] serial_out; end endmodule逻辑说明第一个assign实现了 16 选 1 的功能EN 决定选 A 组还是 B 组ADD 决定组内选哪一位结果就是分时送出的一位数据。第二个 always 块用DEMUX_ADDR作为译码地址把serial_out写到对应端口同时把其他 15 个端口清零这样每一拍只有一个端口上有数据。参数说明ADD是 3 位取值范围 0~7DEMUX_ADDR是 4 位取值范围 0~15Z位宽 16对应 z0~z15。如果你要完全保持原文档的接口形式把 A0~A7 拆成独立输入端口也可以但建议在模块内部用input [7:0] A这种向量写法仿真时给A 8h5A一句话就能赋值比 8 个独立端口逐个赋值省事得多。3.3 QuartusII 建工程与波形仿真步骤我一般按照下面这套流程走在 QuartusII 14.0 到 20.x 各版本上都适用。第一步新建工程File → New Project Wizard工程名填mux_demux器件族选择 Cyclone IV 或 Cyclone 10 LP 都行具体型号随意因为纯组合逻辑不占用资源随便选一个能过编译的型号即可。第二步把上面的 Verilog 代码保存成Vrfenshi.v添加到工程。第三步Processing → Start Analysis Synthesis观察 Message 窗口这个工程应该只有一个 Info 级别的警告关于DEMUX_ADDR悬空输入属正常现象因为测试台中会连接到激励信号。接下来写测试台做行为仿真。新建一个tb_vrfenshi.v用 Quartus 自带的 ModelSim 或 Vivado 的 XSim 都行Quartus 集成的 ModelSim Starter 已经够用timescale 1ns/1ps module tb_vrfenshi; reg EN; reg [2:0] ADD; reg [7:0] A, B; reg [3:0] DEMUX_ADDR; wire serial_out; wire [15:0] Z; Vrfenshi uut ( .EN(EN), .ADD(ADD), .A(A), .B(B), .DEMUX_ADDR(DEMUX_ADDR), .H(serial_out), .Z(Z) ); initial begin A 8h5A; B 8hA5; EN 0; // EN0 时 A 组的通道扫描 for (ADD 0; ADD 8; ADD ADD 1) begin // 让译码器地址跟随通道地址变化 DEMUX_ADDR {1b0, ADD}; #10; end // EN1 时 B 组的通道扫描 EN 1; for (ADD 0; ADD 8; ADD ADD 1) begin DEMUX_ADDR {1b1, ADD}; #10; end $stop; end endmodule测试台逻辑说明A 组数据设为5A二进制 01011010B 组设为A5二进制 10100101两组数据在每一位上互补这样仿真波形上能一眼看清选择的到底是 A 还是 B。DEMUX_ADDR由 EN 与 ADD 拼接而成模拟了真值表中地址编码的关系。每 10ns 扫描一个通道跑完 16 路总共 160ns。如果你用的是 ModelSim 命令行进入仿真目录后执行vsim work.tb_vrfenshi然后 add wave 添加所有信号就能看波形。仿真结果的关键观察点serial_out在 EN0 时应依次输出 A0~A7也就是 5A 从低位到高位逐位出现EN1 时应依次输出 B0~B7。对应地Z[DEMUX_ADDR]在每一拍都等于serial_out的值其他端口保持 0。这两条都满足就说明分时传送链路功能正确。4. 避坑指南多通道分时仿真里最常见的五个翻车点4.1 EN 命名误导它其实是地址位不是使能端现象按“使能”的直觉理解EN1 应该让电路工作但仿真时 EN1 反而只输出 B 组数据A 组数据不见了。原因在这份设计里EN 实际承担的是高位地址功能等价于 16 选 1 选择器的 A3 地址线。把它命名为 EN 只是课程设计的习惯容易让人误以为是全局使能。解决读真值表时把 EN 当作地址最高位不要当作电路总开关。如果想让这个信号语义更清晰可以重命名为SEL_H。硬件上若确实需要全局使能再单独加一个与门控制串行输出。4.2 敏感列表不全与按位与条件导致仿真结果随机现象原代码放仿真器里跑有时候波形全对有时候输出全是 X换一台机器结果还不一样。原因always (EN or A or B or ADD)在旧版本 Verilog 里要求把用到的信号写全漏掉一个就会出现仿真与综合不一致。更隐蔽的是if(A B ADD)8 位向量和 3 位向量按位与结果是一个 8 位中间值而 if 条件只判断整体是否为真这在仿真中会产生不可控的行为。解决组合逻辑 always 块统一写always *让工具自动推导敏感列表。条件判断改成assign serial_out EN ? B[ADD] : A[ADD];这样的确定性表达式仿真结果就和真值表严格对应了。4.3 case 枚举笔误地址跳号和通道重复现象仿真时发现某个通道永远没有输出或者两个不同地址输出相同数据。我见过一份手抄代码里4: Z A5这一行之后直接跳到6: Z A6A4 通道凭空消失。原因逐行手写 case 分支时序号和数据名极易错位一旦中间差一行后面的映射全部错位。解决写选择器逻辑优先用[ADD]索引语法根本不需要 case。只有遇到“地址不连续”的场景才用 case比如 3-8 译码器输出独热码。索引语法不仅是代码量的问题它从根本上消灭了这类映射错误。4.4 阻塞赋值在组合逻辑里推断出 latch现象综合后 Quartus 报告生成了 16 个 latch也就是锁存器仿真时序图和实际硬件行为对不上。这个问题在这个设计里很典型因为原代码的 if 分支没有 elseelse 分支里也没有给输出赋默认值。原因组合逻辑 always 块如果存在某个输入组合下输出不被赋值综合器就会推断出 latch 来保持上一次的值。latch 会给时序分析带来很大麻烦而且它不像触发器那样有明确的时钟约束是 FPGA 设计里很不想见到的东西。解决在 always 块开头先给输出赋默认值比如Z 16b0;然后再按条件覆盖。这也是我在修正代码中采用的做法默认赋值一行就能把 latch 全部消除。4.5 multisim 里使能端接反导致译码器全灭现象multisim 里连线完成后拨动开关16 个输出端全部是高电平没有任何一路被点亮。原因74×154 有两个使能端G1 是高电平有效G2 是低电平有效。很多同学只记得 151 的使能是低有效想当然把 154 的使能也接地结果 G1 一直是 0译码器被全局禁用输出自然全 1。解决查器件手册确认每个引脚的使能极性。151 的 ~E 接地154 的 G1 接高电平、~G2 接地。这个接线步骤做完后用万用表测一下 G1 引脚电压确认是 5V 再继续可以省掉大半天的排查时间。5. 验证方法把 multisim 与 QuartusII 波形对着看四个关键观察点5.1 同一测试用例下两组波形的对齐说实话我最早跑这个设计时也踩过 154 输出低电平有效的坑。multisim 里 74×154 的输出本来就是低电平有效而 QuartusII 仿真里我的 Verilog 写的是正逻辑两边波形对不上我还以为是代码写错了。后来把 154 输出的低有效考虑进去才明白问题出在我自己的预期上。所以验证的第一步是先明确两套环境各自的极性约定。multisim 用 74×154输出低电平才表示对应的那一通道被选中QuartusII 里我写的译码器输出是正逻辑选中为 1。同一个真值表两边的波形极性相反是正常现象对照时要把这一层换算关系先写在纸上不然很容易误判。5.2 用扫描法 2 分钟验证全部 16 路手工一个个拨开关验证太慢了。我一般会把地址输入接成一个二进制计数器时钟接一个低频方波这样 16 个地址自动循环用逻辑分析仪或者示波器看串行传输线就可以看到数据按通道顺序逐位出现。具体操作是multisim 里加一个计数器元件输出 4 位接到 154 的地址端再把低位 3 位同时接到 151 的地址端EN 接计数器的最高位。跑完后观察传输线上的数据是否按 z0 到 z15 的顺序依次出现。这里要注意如果计数器是异步清零复位瞬间会有一段毛刺最好在观察窗口跳过前面两个时钟周期。5.3 验证完记得做的最后一件事验证通过后我习惯把 Verilog 的测试台波形导出成图片存档然后在 multisim 里截取同一地址范围的示波器波形图两张图并排放在课程设计报告里。不要小看这一步答辩时老师问“你怎么证明你的设计是对的”直接调速到同一时刻的波形截图比解释一百句话都管用。从那以后我每次做组合逻辑验证都强制走一遍“真值表 → Verilog 仿真波型 → multisim 硬件时序”三对照的流程确认三个结果完全一致才收工。希望这份拆解和修正后的代码能帮到你少走几趟我当年踩过的弯路。本文还有配套的精品资源点击获取