实验5:Logisim

截止日期:3月12日星期四晚上11:59:59 PT

本实验介绍Logisim——一个用于设计和模拟数字逻辑电路的教育工具。这是项目3的重要准备。

实验幻灯片


设置

您必须在本地机器上完成此实验。如果需要重新设置本地机器,请参阅实验0

在本地机器的labs目录中,拉取您在过去实验中可能做的任何更改:

git pull origin main

仍然在本地机器的labs目录中,使用以下命令拉取本实验的文件:

git pull starter main

如果遇到任何git错误,请查看常见错误页面。

仍然在labs目录中,运行以下命令下载最新版本的Logisim:

bash tools/download_tools.sh

本实验中的所有工作都将使用Logisim Evolution完成。

开始前的一些重要警告:

  • Logisim是一个GUI程序,因此不能在无图形界面环境(WSL、SSH等)中轻松使用。请在具有GUI、Java 9+和Python 3.6+的本地环境中运行它。如果您的本地系统是macOS或Linux,您可能已经准备好了。如果您使用Windows,请使用Git Bash,它在Windows上运行并支持GUI。
  • 请使用我们分发的Logisim版本,因为它与互联网上的其他版本不同(包含bug修复和课程特定内容)
  • 不要移动工作人员提供的输入/输出引脚;如果引脚移动,您的电路将无法正确测试。如果您的电路未通过测试但您认为它是正确的,请检查您的电路是否适合tests/ex#_test.circ中的相应测试框架
  • Logisim不会自动保存您的工作。工作时请记住频繁保存(并提交)!

可能的设置错误

  • 在Windows 10上尝试运行Python时出现"Permission Denied"(权限拒绝)
    1. 在Windows搜索提示符中搜索"app execution alias"(应用执行别名)。点击"Manage app execution aliases"(管理应用执行别名),它是"System Setting"(系统设置)的一部分
    2. 通过切换相应的可执行文件来禁用商店版本的Python。
      截图
  • java.lang.UnsupportedClassVersionError
    Exception in thread "main" java.lang.UnsupportedClassVersionError: com/cburch/logisim/Main has been compiled by a more recent version of the Java Runtime (class file version 60.0), this version of the Java Runtime only recognizes class file versions up to 52.0
    
    您需要更新到Java 16+。请按照实验0的设置说明操作。

练习1:介绍

与Venus类似,您可以从lab05文件夹内打开Logisim,使用命令:

java -jar ../tools/logisim-evolution.jar ## 如果在不同的文件夹中,请使用相应的相对路径

短暂的启动序列后,应该会出现一个看起来有点古老的窗口。如果没有出现,请检查终端中的错误。

我们将从创建一个非常简单的电路开始,只是为了感受放置门和电线的感觉。开始之前,请注意一个有用的功能:缩放功能!它在左下角,将在接下来的几周内让您的生活变得更加轻松。缩放缩放缩放。

Logisim缩放功能位于左下角

构建我们的电路

  1. AND门图标 首先点击AND门按钮。这将使AND门的阴影跟随您的光标移动。在主原理图窗口中单击一次以放置一个AND门。

  2. 输入引脚图标 点击Input Pin(输入引脚)按钮。现在,在您的AND门左侧的某个位置放置两个输入引脚。

  3. 输出引脚图标 点击Output Pin(输出引脚)按钮。然后在您的AND门右侧的某个位置放置一个输出引脚。此时您的原理图应该看起来像这样:

    Logisim 中的电路:左侧两个输入引脚值为0,中间AND门,右侧输出引脚值为U,均未连接

  4. 选择工具图标 点击Select tool(选择工具)按钮。点击并拖动以将2个输入引脚连接到AND门左侧的2个输入端。您只能绘制垂直和水平的电线。只需水平绘制一条电线,释放鼠标按钮,然后从电线末端开始点击并拖动以继续垂直绘制。重复相同的过程,将AND门右侧的输出端连接到输出引脚。完成这些步骤后,您的原理图应该看起来类似于此:

    Logisim 中的电路:左侧两个输入引脚值为0,连接到中间AND门,右侧输出引脚值为0

  5. 戳工具图标 最后,Poke工具在您点击引脚时会切换引脚的值。如果您在电线上使用Poke工具,它将显示电线上的值。选择Poke工具,尝试点击原理图中的输入引脚,并观察发生了什么。输出是否符合您认为AND门应该做的事情?现在,尝试直接点击一根电线。该电线上的当前值应该会弹出;这在您以后构建更复杂的电路时会非常有用。

  6. 现在,删除电线,并尝试将每个输入引脚连接到AND门上的另一个引脚,使电线交叉。一个极端的例子:

    Logisim交叉连线电路演示

    如果您在创建电线时将其拖动穿过另一根电线而不停下,电线不会连接。如果您在创建电线时在另一根电线上方停止拖动,将创建一个连接点(大圆圈),电线将连接。设计电路时一定要注意连接点!

电线颜色和值列表

请查看此列表。尝试自己重新创建每种颜色可能会有所帮助。

Logisim电线颜色和值演示电路

颜色含义
深绿色1位电线的值为0
亮绿色1位电线的值为1
黑色多位电线(许多组件具有位宽属性,可以在左下角的属性菜单中配置)
红色(值为EEEE电线上有多个值(在这种情况下,来自2个输入的01)。另外,记住在电线连接点会出现一个大圆圈。
蓝色(值为UUUU电线处于浮动状态(即没有已知值)
橙色电线连接到具有不同位宽的组件。一个简单的例子是1位输入引脚连接到2位输出引脚。在所示示例中,MUX后面有一根稍微隐藏的电线,将2位低位数据线连接到1位选择线。要注意这些情况!

无障碍提示:如果您有残疾且难以识别这些颜色,请随意使用更方便的颜色集。要执行此操作,请转到File -> Preferences -> Simulation Tab(文件->首选项->模拟选项卡)。当您在OH或Ed上展示电路时,请告知课程工作人员此更改,因为我们经常使用颜色作为调试工具。

练习2:子电路

就像C程序可以包含辅助函数一样,原理图可以包含辅助子电路。在本实验的这一部分,我们将创建几个子电路来演示它们的用法。

注意:Logisim Evolution通常不允许使用带空格或符号的名称、以数字开头的名称或与关键字冲突的名称(例如NAND)。

  1. 打开练习2的原理图(File -> Open -> lab05/ex2.circ)。

  2. 通过双击左侧电路选择器中的AND2来打开AND2示例子电路。

    请注意末尾的2;因为有一个名为AND的组件,所以我们不能将其称为AND。 我们创建了一个演示电路供您参考。它有2个1位输入引脚AB,并将A & B的结果发送到RESULT输出引脚。这应该与您刚刚制作的练习电路非常相似。

  3. 现在,打开NAND2子电路。是时候制作您自己的电路了!使用左侧Gates库中的内置NAND门来填充此电路(即仅使用ANDORNOT门;它们在窗口顶部的工具栏中作为小图标提供,或在电路选择器的Gates库中)。完成后,类似地填充NOR2XOR2MUX2(2选1 MUX)和MUX4(4选1 MUX)。请注意,NANDNORXORMUX已存在于Logisim中。本练习旨在帮助您理解如何使用子电路。

    • 请不要更改子电路的名称或创建新的子电路,否则您的电路可能无法正常工作
    • 除了ANDORNOT之外,不要使用任何内置门。但是,一旦您构建了一个子电路,您可以(并且鼓励)使用它来构建其他电路。您可以通过在电路选择器中单击子电路,然后像放置AND/NOT/OR门一样放置它来实现这一点
    • 为每个电路写出真值表会有所帮助。您可能还会发现复习关于如何构建这些门的讲座幻灯片很有用
    • 这份组合逻辑块讲义可能对您的MUX实现有用
    • 对于4-to-1 MUXSEL0SEL1分别对应于2位选择器的第0位和第1位。确保不要切换它们!

测试

打开终端会话并转到lab05文件夹。我们为每个练习提供了测试,您可以使用python3 test.py运行。对于每个测试,您的电路在测试框架电路(tests/ex2-test.circ)中运行,其输出与该测试的参考输出(tests/out/ex2-test.ref)进行比较。在输出文件中,每列对应主电路上的一个输入/输出引脚,每行显示一组输入和电路产生的相应输出。如果您的电路输出(tests/out/ex2-test.out)不同,您可以将其与参考输出文件进行比较;diff命令可能会有所帮助。

  • 请注意,输出文件通过在每个值之间添加制表符(\t)来"格式化",当制表符显示为8个空格宽时,它们看起来最好。8个或更多字符的值和列标题可能会打乱对齐,所以要注意这些!
  • 不要修改参考输出文件,否则本地测试可能会产生不正确的结果
  • 您不需要编辑本实验的测试框架电路。但是,查看一下可能会很有用;我们将在下一个实验和项目3中做类似的事情!

检查点

在这一点上,请确保您熟悉Logisim环境、创建子电路以及在其他电路中重用此类电路。

练习3:存储状态

让我们实现一个重复递增值的电路。这个电路与您到目前为止为实验构建的电路之间的区别在于,它将把这个值作为状态存储在寄存器中。

  1. 打开练习3的原理图(File -> Open -> lab05/ex3.circ)并转到空的AddMachine电路。

    1. 记住要经常保存,并避免移动或编辑提供的输入/输出引脚
  2. Arithmetic库(左侧的电路选择器)中选择Adder子电路,并将加法器放置到您的AddMachine子电路中。

  3. Memory库中选择Register(寄存器),并将一个寄存器放置到您的子电路中。下面是一张说明寄存器各部分的图片。

  4. clk输入引脚连接到寄存器上的时钟引脚。通常,最好让电路中的所有组件使用同一个时钟,以便所有内容同步。在这种情况下,测试框架为其寄存器使用时钟,因此它通过这里的clk引脚将该时钟信号传递给您电路的寄存器。将来,如果您正在处理一个没有现有时钟信号的电路,可以使用Wiring库中的新Clock(时钟)来创建自己的时钟。

  5. 将加法器的输出连接到寄存器的输入,并将寄存器的输出连接到加法器的输入。

    • 当您尝试连接组件时,可能会收到"Incompatible widths"(不兼容的宽度)错误。这意味着您的电线正试图连接两个具有不同位宽的引脚。如果您使用Selection工具(顶部工具栏上的鼠标指针图标)单击一个组件,您会注意到窗口左下角字段中有一个Data Bits(数据位)属性。该值决定了组件输入和输出的位数。确保加法器和寄存器的数据位宽度都为8,这样"Incompatible widths"错误应该会得到解决。
  6. 将一个值为1的8位常量连接到加法器的第二个输入。您可以在Wiring库中找到Constant(常量)电路元件。要将其值更改为1,只需在Value属性中输入1并按Enter。现在您应该看到该值为0x1(Logisim会自动将您输入的十进制值转换为十六进制)。

  7. 将两个输出引脚连接到您的电路,以便您可以监控加法器和寄存器的输出。加法器的输出应连接到ADD_OUT,寄存器的输出应连接到REG_OUT。因此,最后您的电路应该看起来类似于:

  8. 现在,打开本练习的测试电路(lab05/tests/ex3-test.circ)。在左上角,我们有一个小型电路(类似于您的AddMachine)来跟踪当前周期。在其下方,您应该看到您的AddMachine电路连接到时钟和一些输出引脚。

  9. 通过转到Simulate -> Tick Half Cycle(模拟->半周期滴答)(Command/Control + T)来滴答您的电路一次。您的AddMachine的输出应该增加了!此外,时钟现在应该是亮绿色的。

    这对项目3极其重要,所以请确保您知道如何滴答时钟和点击电线。

    如果您再次Tick Half Cycle(半周期滴答),您会注意到时钟变回深绿色,但数字不会改变。这是因为寄存器默认是上升沿触发的(即从低时钟信号变为高信号时触发)。

    如果您对查看半周期的变化不太感兴趣,也可以使用Simulate -> Tick Full Cycle(模拟->全周期滴答)(F2)。

  10. 手动滴答电路可能会很累。好消息是:Logisim可以为您滴答电路!转到Simulate -> Ticks Enabled/Enable Clock Ticks(模拟->启用滴答/启用时钟滴答)(Command/Control + K)。现在您的电路应该自动计数了!

    如果您想让电路运行得更快,可以在Simulate -> Tick Frequency(模拟->滴答频率)中更改滴答频率。要停止,请再次点击Ticks Enabled//Enable Clock Ticks(启用滴答//启用时钟滴答)(Command/Control + K)。如果您想重置电路,请使用Simulate -> Reset Simulation(模拟->重置模拟)(Command/Control + R)。

  11. 完成后,尝试运行提供的测试(使用python3 test.py)。

检查点

在这一点上,请确保您熟悉在Logisim环境中设计和模拟使用组合逻辑状态元件(寄存器)混合的简单数字逻辑电路。


高级Logisim功能

以下是三个Logisim功能,它们既可以为您节省大量时间,又可以使您的电路看起来更整洁。

分割器

分割器允许您将一个多位值拆分成较小的部分,或者(尽管名称如此)将多个一位或多位的值组合成单个值。在这里,我们将4位二进制数1100拆分为1100,交换它们的位置,并将它们与0组合以创建最终的5位数00110

(使用Select工具)点击分割器以在侧边栏(左下角)中获取其属性。您可以配置分割器上的臂数和每个臂上存在的位等属性。对于上面的电路,左侧和右侧分割器的属性如下所示:

请注意有一个名为Facing(朝向)的属性。您可以使用它来旋转分割器。在上面的示例中,右侧的分割器朝向West(西),而左侧的分割器朝向East(东)。

如果您看到橙色的错误电线,这意味着您的输入位宽与输出位宽不匹配。确保在用电线连接两个组件时,在该组件的菜单中正确设置位宽。

隧道

隧道允许您绘制一条"隐形电线"来将两个点绑定在一起。隧道按赋予电线的区分大小写的标签分组。它们用于连接电线,如下所示:

这实际上相当于:

应该注意哪些电线与哪些其他电线通过隧道连接,例如在这种情况下:

这实际上相当于:

我们强烈建议您在Logisim中使用隧道,因为它们使您的电路看起来更整洁(减少电线混乱),这意味着更容易调试。

扩展器

当更改电线的宽度时,为了清晰起见,您应该使用位扩展器。例如,考虑以下将8位电线零扩展为16位电线的实现:

与分割器相比,扩展器一目了然。在处理复杂电路时,这变得特别有帮助。

此外,考虑丢弃位的情况。尽管名称如此,扩展器也可以执行此操作:

虽然分割器更简约,但也稍微难以阅读。


练习4:循环右移

凭借您对分割器的了解以及对多路复用器的知识和经验,您已准备好实现一个非平凡的组合逻辑块:RotRight,代表"循环右移"(Rotate Right)。其思想是RotRight将输入INPUT0的位模式向右循环移动AMOUNT位。因此,如果INPUT00b1000000000000101AMOUNT0b0011(十进制的3),则该块的输出将是0b1011000000000000。请注意,最右边的3位从值的右端移出并回到左端。这可以通过位运算R = A >> B | A << (16 - B)来表示。

实现一个名为RotRight的子电路,具有以下输入:

  • INPUT0(16位),要旋转的16位输入
  • AMOUNT(4位),旋转量(为什么是4位?)

您可以在ex4.circ中找到起始子电路。记住要经常保存,并避免移动或编辑提供的输入/输出引脚

输出应该是INPUT0向右旋转AMOUNT位位置,如上所述。您不允许在解决方案中使用Logisim移位器,但允许使用所有其他组合逻辑(MUX、常量、门等)。Logisim的内置MUX(在Plexers菜单下找到)可能特别有帮助。您的解决方案不应涉及时钟或任何时钟元件(如寄存器)。

  • 我们为您提供了rot1rot2rot4rot8的框架,它们将分别将输入旋转1、2、4和8位。您应该实现这些子电路并在RotRight的实现中使用它们。
提示

您可以使用提供的子电路旋转0-15范围内的任何数字。例如,要旋转9位,您可以先旋转8位,然后旋转1位。

完成后,尝试运行提供的测试。

练习5:反思和反馈表

我们每周都在努力改进课程——请填写此调查告诉我们您到目前为止在讨论课和实验中的体验!

练习6:[可选(OPTIONAL)]学期中期反馈表

我们还在进行一项学期中期调查,以了解您在整个课程中的体验。请填写此调查以获得额外学分


提交

保存、提交并推送您的工作,然后在Gradescope上提交到实验5作业。