简介:这份 docx 文档是数字电子技术实验课程的集成计数器实验报告,面向电子信息、通信、自动化等专业的本科生与实验初学者,帮助读者理解中规模计数器的工作原理、引脚配置与实验验证方法。压缩包共 1 个 docx 文件,约 98KB,内容涵盖实验目的、实验设备、实验原理、实验原理图及实验结果等完整环节,便于直接参照撰写或复盘自己的实验报告。文档围绕 74LS90 这款二-五-十进制异步计数器展开,讲清了二进制、五进制与十进制计数器的分类依据,同步与异步、加法与可逆计数器的区别,以及 Ro 异步清零端、So 异步置九端、CP1 与 CP2 两个时钟输入端和 Q0 至 Q3 计数输出端的功能与接法,并给出 8421 码与 5421 码两种输出配置的差异。实验部分记录了用函数信号发生器产生 5V、3Hz、偏移 2.5V 方波作为计数脉冲,最终在解码器上依次显示 0 至 9 的验证过程。目前已有 2549 人学习,适合对照接线、核对结果并巩固中规模集成电路的使用思路。
1. 从一份"集成计数器实验报告"说起:数电实验里最容易翻车的为什么是计数器的级联
数电实验课上,组合逻辑电路的报告通常一次就过,真正卡人的是时序电路那一批,尤其是集成计数器。一份"集成计数器实验报告.docx"被打回,多半不是原理写错,而是波形、数据表和结论三样对不上:接线用的是 74LS161,报告里却按 74LS160 的十进制进位去描述;清零端画成异步,芯片其实是同步清零;级联两片时把 RCO 直接怼到下一片的 CLK 上,计数器就开始跳变。
问题出在集成计数器的"行为"藏在真值表和时序图里,不在电路符号上。74LS160 和 74LS163 的引脚排布几乎一样,清零方式却差一个时钟沿;CD4017 长得像计数器,实际是脉冲分配器。这篇把选型判据、仿真验证、数据整理和报告文档生成串成一条链,让每一次实验的波形和数据都能对得上芯片手册。适合正在上数电实验、需要交报告的人,也适合面试前想快速回忆 74LS163 与 CD4017 差别的人。
2. 集成计数器选型:74LS160/161/163 与 CD4017 的差别,以及实验前的准备清单
选型错一步,后面波形全废。集成计数器分成几个家族:TTL 的 74LS160/161/162/163 是四位同步计数器,74LS192 是同步可逆计数器,CMOS 的 CD4017 是十进制计数/脉冲分配器。它们的功能脚名字高度相似——CLR、LOAD、ENP、ENT、RCO——但有效电平、有效时刻完全不同。实验报告里最该写清楚的,恰好就是这几点。
2.1 同步与异步清零/置数:一句话判据与三个必查引脚
异步清零的意思是:清零信号一有效,输出立刻变 0,不用等时钟沿。同步清零的意思是:清零信号有效后,必须等到下一个有效时钟沿,输出才归零。判断方法很直接——翻数据手册的功能表,看 CLR 那一行有没有画时钟符号,或者看"输出变化"的条件里是否绑定了时钟。
74LS160/161 是异步清零加同步置数,74LS162/163 是同步清零加同步置数,74LS192 的清零和置数都是异步的。这四片在实验箱上经常并排插着,只看型号不看手册,接线必然出问题。
必查的三个引脚是 CLR、LOAD、RCO。CLR 低有效还是高有效、LOAD 低有效还是高有效、RCO 是在计数值到顶时有效还是要配合 ENT 才有效,这三条决定了你的级联线能不能接对。
提示:RCO 不是无条件输出的。74LS160/161/163 的 RCO 需要 ENT 为高电平、且计数值处在满量程时才拉高,级联时上一片的 ENT 和 RCO 都要参与,否则低位片进位会丢。
2.2 十进制、二进制与可逆计数器的适用场景
不同型号不是随便挑的,实验题目给的目标模值决定了选择范围。
| 型号 | 计数进制 | 清零方式 | 置数方式 | 典型用途 |
|---|---|---|---|---|
| 74LS160 | 十进制(0-9) | 异步 | 同步 | 秒计数、8421BCD 输出 |
| 74LS161 | 十六进制(0-15) | 异步 | 同步 | 分频、地址计数 |
| 74LS162 | 十进制(0-9) | 同步 | 同步 | 需要无毛刺清零的场合 |
| 74LS163 | 十六进制(0-15) | 同步 | 同步 | 任意模值计数器改装 |
| 74LS192 | 十进制可逆 | 异步 | 异步 | 加减计数、倒计时 |
| CD4017 | 十进制分配 | 异步(MR 高有效) | 无 | 流水灯、时序分配 |
如果实验要求输出直接驱动数码管显示十进制,74LS160 或 74LS162 更省事;如果要做模 N 的任意进制计数器,74LS163 因为同步清零、同步置数,改装起来状态最干净,不会像异步清零那样出现一个极短的杂散状态。
2.3 实验前必做的三件事:引脚表、逻辑电平、电源
上电之前,先画一张自己的引脚功能表,把每个脚的名字、方向、有效电平写上去。DIP-16 封装里 VCC 在 16 脚、GND 在 8 脚,这是 74 系列小规模芯片的通用约定,接反了芯片基本就废了。
逻辑电平要记清楚。TTL 输入低电平上限是 0.8V,高电平下限是 2.0V;输出低电平不超过 0.4V,高电平不低于 2.4V。CMOS 的 CD4017 工作电压范围宽,但在 5V 供电下与 TTL 电平兼容,直接对接没问题。悬空的输入脚在实验箱上会被噪声拉来拉去,ENP、ENT、CLR、LOAD 这些脚一个都不能空,不用的必须拉到确定电平。
电源方面,5V 供电的偏差控制在 ±5% 以内,实验箱和仿真环境的默认值都是 5V,报告里写实测电压时顺手量一下,比抄标称值可信。
2.4 用 Verilog 把 74LS163 的行为写成可仿真模型
在动手接线之前,先写一遍行为模型,把手册里的时序关系固化下来,后面仿真波形就是接线对错的参照。
module ttl163 ( input wire clk, input wire clr_n, // 同步清零,低有效 input wire load_n, // 同步置数,低有效 input wire [3:0] d, // 置数输入 input wire enp, // 计数使能 P input wire ent, // 计数使能 T,同时控制 RCO output reg [3:0] q, // 计数输出 QA~QD output wire rco // 进位输出 ); // 同步逻辑:清零、置数、计数都在同一时钟沿判断 always @(posedge clk) begin if (!clr_n) q <= 4'h0; // 同步清零 else if (!load_n) q <= d; // 同步置数 else if (enp && ent) q <= q + 1'b1; // 两使能同时有效才计数 end // RCO 只在 ENT 有效且计数到满量程时拉高 assign rco = ent && (q == 4'hF); endmodule这段代码里最容易写错的是rco的条件。很多人只写q == 4'hF,结果 ENT 拉低时 RCO 还在输出高电平,级联时就多进了一位。另一个是清零判断放在always块内的if里,而不是写在敏感列表里,这正好对应"同步"这两个字——异步清零要写成always @(posedge clk or negedge clr_n)。
参数上,enp和ent的差别只在 RCO 上,计数时两者都要为高,做保持功能时把它们拉低即可,不用额外清除计数值。
3. 用仿真跑通集成计数器实验:testbench、波形观测与数据导出
模型有了,接着搭测试平台。仿真跑通的意义在于,你可以在不碰实验箱的情况下,先把清零、置数、级联这些时序关系验证一遍,报告里的波形图也就有了干净的来源。
3.1 最小 testbench:时钟、同步清零与同步置数的激励顺序
激励顺序要体现"同步"和"异步"的区别,否则波形上没有区分度。
`timescale 1ns/1ps module tb_ttl163; reg clk = 0; reg clr_n = 1; reg load_n = 1; reg [3:0] d = 4'h0; reg enp = 1; reg ent = 1; wire [3:0] q; wire rco; ttl163 u_dut ( .clk(clk), .clr_n(clr_n), .load_n(load_n), .d(d), .enp(enp), .ent(ent), .q(q), .rco(rco) ); always #10 clk = ~clk; // 20ns 周期,即 50MHz initial begin $dumpfile("tb_ttl163.vcd"); $dumpvars(0, tb_ttl163); // 阶段一:同步清零,清零信号跨过时钟沿才生效 clr_n = 0; #25; // 故意不是 20 的整数倍,观察同步效果 clr_n = 1; #200; // 阶段二:同步置数,装入 5 load_n = 0; d = 4'h5; #20; // 保持到下一个时钟沿 load_n = 1; #200; // 阶段三:计到满量程,观察 RCO #200; $finish; end endmodule#25这个非整数倍延时是故意留的。同步清零只在时钟上升沿采样clr_n,所以清零信号什么时候来不重要,重要的是它有没有覆盖住一个上升沿。如果换成异步清零的 74LS161 模型,clr_n一拉低输出立刻归零,波形上能明显看出差别,这正是报告里值得写的一段对比。
$dumpvars把波形写进 VCD 文件,用 GTKWave 或者仿真器自带的波形窗口都能打开。想看rco和q的相位关系,把两者放在同一组里,触发点设在q从 F 跳 0 的那一帧。
3.2 关键波形观测点:进位链、置数时刻与异步清零毛刺
波形不是截下来就行,得知道看哪里。级联实验中,重点盯三个位置。
第一是低位片的 RCO 到高位片的 ENT/ENP 是否在同一时钟沿被采样。由于 RCO 是组合输出,它会随计数值变化,如果直接拿它当时钟用,高位片会在低位片进位的瞬间被触发,这是典型的异步级联错误做法。
第二是置数时刻。同步置数要求 LOAD 有效时正好压住一个时钟沿,波形上表现为load_n拉低期间有一个上升沿,q在沿后变成d的值。如果load_n只持续了半个周期,这次置数会被漏掉。
第三是清零毛刺。异步清零的芯片在做模值改装时,计数值会闪过一个极短的杂散状态,波形放大后能看到一个宽度只有几纳秒的台阶。报告里把这处毛刺标出来,比写一句"工作正常"有信息量得多。
3.3 把仿真数据导成实验报告里的数据表
仿真跑完,手工从波形上抄数容易出错,让 testbench 直接输出 CSV 更省事。
integer fd; initial fd = $fopen("counter_trace.csv", "w"); initial $fwrite(fd, "time_ns,clk,clr_n,load_n,q_hex,q_dec,rco\n"); always @(posedge clk) begin $fwrite(fd, "%0t,%b,%b,%b,%h,%0d,%b\n", $time, clk, clr_n, load_n, q, q, rco); end$time取的是当前仿真时间,%h输出十六进制、%0d输出十进制,注意q在 Verilog 里是 4 位向量,十进制格式会按无符号解释,正好对应计数值。导出的 CSV 可以直接用表格软件打开,也可以作为附录贴进报告。
| 时钟序号 | 状态 QA-QD | 十进制值 | RCO | 说明 |
|---|---|---|---|---|
| 1 | 0000 | 0 | 0 | 同步清零后 |
| 2 | 0001 | 1 | 0 | 正常计数 |
| 3 | 0010 | 2 | 0 | 正常计数 |
| ... | ... | ... | ... | ... |
| 17 | 1111 | 15 | 1 | 满量程,RCO 拉高 |
| 18 | 0000 | 0 | 0 | 回卷并产生进位 |
这张表就是报告"实验数据"栏目的主体,配合波形图,数据和图形互相印证,审阅的人一眼能看出你真的跑过仿真而不是编的。
4. 集成计数器实验报告怎么写:用 python-docx 生成参数表与波形占位
到了一步,实验做完了,报告得交。与其每次都手动调整表格列宽和标题字号,不如把固定栏目做成模板,数据从 CSV 读进来直接落进 docx。
4.1 报告骨架:从实验目的到结论的固定栏目
一份集成计数器实验报告,栏目基本是固定的,区别只在内容量。把结构定死,每次填空就行。
| 栏目 | 内容要求 | 常见扣分点 |
|---|---|---|
| 实验目的 | 写明验证哪款芯片的哪种功能 | 照抄指导书 |
| 实验器材 | 型号、数量、实验箱编号 | 漏写芯片型号 |
| 原理说明 | 真值表加时序图,标注同步/异步 | 时序图不标时钟沿 |
| 实验电路 | 接线图,标注引脚号 | 只画方块图不标管脚 |
| 实验数据 | 状态转移表加实测波形 | 数据与波形对不上 |
| 误差分析 | 毛刺、悬空脚、竞争冒险 | 只写"误差在允许范围" |
| 结论 | 与仿真或理论值对比 | 与数据无关的空话 |
4.2 用 python-docx 自动填参数表和真值表
先装依赖,再跑脚本,把前面导出的 CSV 读进表格。
from docx import Document from docx.shared import Pt import csv doc = Document() # 一级标题 h = doc.add_heading("集成计数器实验报告", level=0) doc.add_heading("一、实验参数", level=1) # 芯片参数表:型号 / 进制 / 清零方式 / 置数方式 params = [ ("芯片型号", "74LS163"), ("计数进制", "十六进制(0-15)"), ("清零方式", "同步,低电平有效"), ("置数方式", "同步,低电平有效"), ("工作电压", "5V"), ] t = doc.add_table(rows=1, cols=2) t.style = "Table Grid" t.rows[0].cells[0].text = "参数项" t.rows[0].cells[1].text = "取值" for k, v in params: row = t.add_row().cells row[0].text = k row[1].text = v doc.add_heading("二、实测数据", level=1) # 从仿真导出的 CSV 里取前若干行落表 with open("counter_trace.csv") as f: reader = csv.DictReader(f) rows = [r for r in reader if int(r["time_ns"]) % 20 == 0][:20] t2 = doc.add_table(rows=1, cols=4) t2.style = "Table Grid" for i, name in enumerate(["时间/ns", "QA-QD", "十进制", "RCO"]): t2.rows[0].cells[i].text = name for r in rows: cells = t2.add_row().cells cells[0].text = r["time_ns"] cells[1].text = r["q_hex"] cells[2].text = r["q_dec"] cells[3].text = r["rco"] # 波形图占位:截图文件补齐后手动替换 doc.add_heading("三、波形记录", level=1) doc.add_paragraph("图 1 同步清零与置数波形(GTKWave 截图)") doc.add_paragraph("图 2 满量程进位波形") doc.save("集成计数器实验报告.docx")add_heading的level=0生成的是文档标题样式,level=1是一级标题,层级和 Word 导航窗格直接对应。Table Grid是内置样式名,套上之后表格自动带边框,不用手动描线。那个% 20 == 0的筛选是为了只保留时钟沿上的采样点,避免把组合毛刺也写进表格,让数据变得难看。
csv.DictReader依赖第一行的列名,所以 testbench 里$fwrite输出的表头必须和脚本里取的键名完全一致,time_ns、q_hex、q_dec、rco一个字都不能差。
4.3 波形截图规范与误差分析的写法
截图要能自证。坐标轴上的时间刻度必须清晰,至少标出时钟周期;触发点对齐到状态跳变的那一帧;每张图下面写一句图注,说明这张图想证明什么,比如"图 2 中 RCO 在 Q=1111 时拉高,下一时钟沿计数回卷并保持一个周期"。
误差分析不要写成免责声明。异步清零产生的窄脉冲、级联时进位延迟导致的竞争冒险、输入悬空造成的状态漂移,这三类是计数器实验里真实会遇到的。写清楚现象、成因和你怎么规避的,比如在 LOAD 端加了一个对地的下拉电阻,或者把异步改装改成了同步置数方案。
5. 从 N 进制改装到面试追问:集成计数器的进阶技巧与验证方法
实验做完,真正拉开差距的是改装和验证。题目给的往往是"用 74LS163 实现模 12 计数器"这类要求,而手里的芯片只有 4 位二进制,怎么把模值凑出来,靠的是反馈清零和反馈置数两种接法。
5.1 反馈清零与反馈置数的模值计算
反馈清零的思路是让计数器数到某个值就立即归零。用同步清零的 74LS163 做模 N 计数器,因为清零需要一个时钟沿才生效,所以反馈信号要取计数值 N-1。比如模 12,取 QDQCQBQA = 1011,即 11,用与非门接到 CLR。
异步清零的 74LS161 就不一样。清零是即时的,反馈信号要取 N,也就是模 12 时取 1100,计数到 12 的瞬间被强行拉回 0,状态 12 只在输出上闪现一个极窄脉冲。这就是前面说的毛刺来源。
反馈置数的做法是让计数器跑到满量程后跳到某个起点。用 74LS163 实现模 N,置数输入 D 取 2⁴ − N,在 RCO 有效时把 LOAD 拉低,下一个时钟沿装入 D,计数区间变成 D 到 15,正好 N 个状态。模 12 时 D = 16 − 12 = 4,即 0100。
| 方案 | 适用芯片 | 反馈取样值 | 输出毛刺 | 状态区间 |
|---|---|---|---|---|
| 反馈清零 | 74LS163 | N−1 | 无 | 0 ~ N−1 |
| 反馈清零 | 74LS161/160 | N | 有窄脉冲 | 0 ~ N 闪现后归零 |
| 反馈置数 | 74LS163/161 | RCO 触发 | 无 | 2⁴−N ~ 15 |
5.2 自启动验证与常见误用
改装完的计数器未必自启动,这是一个面试高频追问:如果由于上电瞬间的随机状态落到了主循环之外,计数器会不会卡死。验证的方法是遍历所有 2⁴ = 16 个初值,各跑十几个时钟,看是否都回到主循环。
// 自启动验证:枚举初值,统计每个初值能到达的状态集合 initial begin for (int i = 0; i < 16; i = i + 1) begin u_dut.q = i; // 强制初值,需先取消 always 块里的复位 #400; $display("初值 %0d 已遍历,请检查波形是否落入主循环", i); end end这段需要在仿真层级用force或者直接把q设为可写端口,实际跑的时候把每个初值对应的状态轨迹记下来,画成状态图。如果发现有状态绕不回来,说明反馈逻辑存在死循环,得换接法。
常见的误用还有两个:一是把 RCO 直接当下一片的时钟用,形成异步级联,进位延迟会随片数累积;二是忽略 ENT 和 ENP 的区别,做级联时只接了其中一根,结果低位片进位传不上去。面试被问到 74LS163 和 74LS160 的差别,答"一个二进制一个十进制"只是表层,真正到位的是把异步清零与同步清零在改装时带来的毛刺差异一并说出来,再补一句"所以我做模值改装优先选同步清零的型号,反馈取样取 N−1"。
本文还有配套的精品资源,点击获取