Team:USTC-Software/Lab1


折叠导航栏

通常,小屏幕上我们都会折叠导航栏,通过点击来显示导航选项。

提示: 如果你删除 .navbar-expand-md 类,导航链接会一直隐藏,且切换按钮会一直显示。

Lab1实验报告

学号:PB17111642 姓名:左顺

逻辑设计

ALU的实现

  • 明确实验目的:设计一个ALU来实现相应的算术逻辑功能。该ALU的结构可以参见下图:

    ALU

  • 明确ALU的输入输出接口:该ALU包含了5个输入输出端口,每个端口的详细说明如下:

    • s: 功能选择。通过不同的组合实现加,减,与,或,非,异或等运算。由于至少有6种运算操作,由于,我们可以让
    • a,b: 两个操作数,其中对于减运算,a是操作数;对于非运算,a是操作数。在此,为方便起见,可以让
    • y: 运算结果。
    • f: 标志位。进行算术运算时,分别表示进位/借位,溢出,零标志。进行逻辑运算时,只有零标志有效。为此,可以令
  • 逻辑设计:

    • y: 作为结果,y的值是很容易求得的。可用形式公式来表示: 。op表示相应的运算操作。

    • f: 作为标记位,包含:

      • CF: 进位/借位标志。只发生在加法或者减法中,如果最高位产生进位或者借位则 ,否则 .如果是加法操作,则可用 实现;如果是减法运算,同样地,可用 实现。
      • ZF:零标志。只需要让ZF = y == 0即可。
      • OF: 溢出标志。有符号数运算结果溢出时则,否则
  • 整体设计module:根据上面的分析,我们可以很自然的写出相应的ALU的初始化模块:

基于ALU实现Fibonacci 数列的计算

  • 首先,我们已经完成了ALU的实验。那么计算Fibonacci 数列中某一项的时候就可以使用ALU了。这是实验的前提条件。

    Fibo

  • 其次,分析该实验的端口,包含了:

    • f0,f1: 初始数据的端口,作为起始项。
    • rst:重置信号,用于回到最初的状态。
    • clk:时钟信号,可以用于控制计算的进度。即每个时钟沿计算一次。
    • fn:结果,表示现在的Fibonacci数列中的某一项。
  • 接着,进行逻辑设计。我们可以再module里面声明两个变量a, b,一旦有rst信号时,就将f0, f1的值赋给a,b。然后每个时钟沿的时候可以将b的值赋给a,y的值赋给b,这样就实现了Fibonacci数列求解问题。

  • 依然设计出初始化的模块:

核心代码

ALU代码

ALU的实现中已经为其定义好了初始化的模块,唯一没有完成的是alu_snip1里面的内容。那么现在来实现这些逻辑代码。

首先我们需要判断操作的类型,在ALU的实现中已经知道s的位数是3。因此,想要判断操作数的类型,无非是对s进行判断,在这里我选择使用case语句。但是在写分支判断语句之前,先来定义几个常量。

接下来再来写分支判断语句:

这样便已经完成了对具体操作的判断,接下来的工作是在每个分支里面写上代码,完成具体的功能。

注意上述两个代码段的位置不同:前者在module下面,后者在module里面的always块里面。

ALU的实现中我们谈到,y的实现是很容易的。那么现在实现y的逻辑:

为每种操作对应的y赋值后,接下来就该处理 f 的问题了。 首先我们来声明CF,SF,ZF,并且将他们通过assign 的方式来为 f 赋值。

接下来根据ALU的实现中的对f 的分析来进行赋值操作。

到了这一步基本上ALU的设计就算完成了。

Fibonacci数列求解问题

在逻辑设计中我们分析了该问题,并且在已有分析的基础上,构建出了初始化的module。接着,我们同样来实现fibo_snip1中的代码。

首先,由于要使用ALU模块,我们需要定义好相关的变量,然后接着调用ALU,实现代码如下:

接着我们需要处理fn的递归生成了。但是首先来实现rst的功能:

当rst为假的时候,我们需要让a = f0; b = f1;以此达到重置的效果。接下来就要处理a,b值的轮换了。

当rst信号无效的时候,此时a = b; b = fn实现了a,b 值的轮换。

至此,基于ALU的Fibonacci数列求解问题解决!

仿真/下载

ALU

  • 仿真:ALU_sim

  • 下载:

基于ALU的Fibonacci数列求解

  • 仿真:fibo_sim

  • 下载:

结果分析

ALU

  • 资源使用情况:

    ResourceUtilizationAvailablepercentage
    LUT28634000.06
    IO242109.52
  • 仿真图分析:

    • s = 1:此时表示的是加法,当a = 60,b = 10时,此时发生了进位和溢出,相应的f=6。
    • s = 2:此时表示的是减法,当a = 20, b =30时, 此事发生了借位和溢出,相应的f = 6。
    • s = 4:此时表示的是与,当a = 20, b = 30时,两者的与为0,对应零标志位为一。
    • s = 5,6,7: 此时表示的分别是或,非,异或,分析知仿真结果正确。

Fibonacci数列

  • 资源使用情况:

    ResourceUtilizationAvailablepercentage
    LUT38634000.06
    FF241268000.02
    IO202109.52
    BUFG1323.13
  • 仿真图分析:此时初始值是1,2,生成的fn依次为3,5,8,13,21...可知仿真正确。

实验总结

本次实验是第一次试验,碰到了比较多的问题,先总结如下:

  • 在下载到开发板时,不能使用initial语句来初始化,initial语句初始化只能在testbench中使用。
  • 不能交叉使用堵塞,非堵塞型赋值。
  • 一些命令或者函数只能使用在testbench中,不能在module中使用他们。
  • 在使用ALU模块的时候,输入端口的类型是reg,输出端口的类型是wire

意见建议

  • 一些重要的试验参数尽量在PPT正文,而不是备注中说明。比如这一次的实验中关于m,n,k位数的选择。
  • 实验规定尽量一次完成,不要在发布后重新修改实验要求。比如这一次OF和SF的选择。
  • 实验中对于可能产生歧义的地方需要着重说明。比如这一次的Fibonacci数列的实现是否强制使用ALU。
  • 实验报告的逻辑设计部分该写什么,希望助教在本次试验后可以说明一下。

设计与测试代码

ALU

  • 设计代码

  • 测试代码

Fibonacci

  • 设计代码

  • 仿真代码