Line 1: | Line 1: | ||
{{USTC-Software/Header}} | {{USTC-Software/Header}} | ||
<html> | <html> | ||
− | <style type='text/css'>html {overflow-x: initial !important;}:root { --bg-color:#ffffff; --text-color:#333333; --select-text-bg-color:#B5D6FC; --select-text-font-color:auto; --monospace:"Lucida Console",Consolas,"Courier",monospace; } | + | <style type='text/css'> |
+ | .navbar {margin-top: -1em} | ||
+ | html {overflow-x: initial !important;}:root { --bg-color:#ffffff; --text-color:#333333; --select-text-bg-color:#B5D6FC; --select-text-font-color:auto; --monospace:"Lucida Console",Consolas,"Courier",monospace; } | ||
html { font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; } | html { font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; } | ||
body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-size: 1rem; line-height: 1.42857; overflow-x: hidden; background: inherit; } | body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-size: 1rem; line-height: 1.42857; overflow-x: hidden; background: inherit; } |
Revision as of 11:11, 25 July 2019
折叠导航栏
通常,小屏幕上我们都会折叠导航栏,通过点击来显示导航选项。
提示: 如果你删除 .navbar-expand-md 类,导航链接会一直隐藏,且切换按钮会一直显示。
Lab1实验报告
学号:PB17111642 姓名:左顺
逻辑设计
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的初始化模块:
1module ALU(
2input [5:0] a,
3input [5:0] b,
4input [2:0] s,
5output [2:0] f,
6output reg [5:0] y
7);
89// alu_snip1
1011endmodule
基于ALU实现Fibonacci 数列的计算
首先,我们已经完成了ALU的实验。那么计算Fibonacci 数列中某一项的时候就可以使用ALU了。这是实验的前提条件。
其次,分析该实验的端口,包含了:
f0,f1
: 初始数据的端口,作为起始项。rst
:重置信号,用于回到最初的状态。clk
:时钟信号,可以用于控制计算的进度。即每个时钟沿计算一次。fn
:结果,表示现在的Fibonacci数列中的某一项。
接着,进行逻辑设计。我们可以再module里面声明两个变量a, b,一旦有rst信号时,就将f0, f1的值赋给a,b。然后每个时钟沿的时候可以将b的值赋给a,y的值赋给b,这样就实现了Fibonacci数列求解问题。
依然设计出初始化的模块:
xxxxxxxxxx
91module fib(
2input [5:0] f0,
3input [5:0] f1,
4input rst,
5input clk,
6output [5:0] fn
7);
8// fibo_snip1
9endmodule
核心代码
ALU代码
在ALU的实现中已经为其定义好了初始化的模块,唯一没有完成的是alu_snip1
里面的内容。那么现在来实现这些逻辑代码。
首先我们需要判断操作的类型,在ALU的实现中已经知道s的位数是3。因此,想要判断操作数的类型,无非是对s进行判断,在这里我选择使用case
语句。但是在写分支判断语句之前,先来定义几个常量。
xxxxxxxxxx
61parameter OP_ADD 3'b001;
2parameter OP_SUB 3'b010;
3parameter OP_AND 3'b100;
4parameter OP_OR 3'b101;
5parameter OP_NOT 3'b110;
6parameter OP_XOR 3'b111;
接下来再来写分支判断语句:
xxxxxxxxxx
91case(s)
2 OP_ADD:;
3 OP_SUB:;
4 OP_AND:;
5 OP_OR:;
6 OP_NOT:;
7 OP_XOR:;
8 default:;
9endcase
这样便已经完成了对具体操作的判断,接下来的工作是在每个分支里面写上代码,完成具体的功能。
注意上述两个代码段的位置不同:前者在module下面,后者在module里面的always块里面。
在ALU的实现中我们谈到,y的实现是很容易的。那么现在实现y的逻辑:
xxxxxxxxxx
71OP_ADD:y a b;
2OP_SUB:y a b;
3OP_AND:y a b;
4OP_OR: y a b;
5OP_NOT:y a;
6OP_XOR:y a b;
7default:y 0;
为每种操作对应的y赋值后,接下来就该处理 f 的问题了。 首先我们来声明CF,SF,ZF
,并且将他们通过assign 的方式来为 f 赋值。
xxxxxxxxxx
21reg CF 0, SF 0, ZF 0;
2assign f {CF, SF, ZF};
接下来根据ALU的实现中的对f 的分析来进行赋值操作。
xxxxxxxxxx
131always@() begin
2 case(s)
3 OP_ADD:{CF, y} a b;
4 OP_SUB:{CF, y} a b;
5 OP_AND:y a b;
6 OP_OR: y a b;
7 OP_NOT:y a;
8 OP_XOR:y a b;
9 default:y 0;
10 endcase
11 ZF y 0;
12 SF y[5:5];
13end
到了这一步基本上ALU的设计就算完成了。
Fibonacci数列求解问题
在逻辑设计中我们分析了该问题,并且在已有分析的基础上,构建出了初始化的module。接着,我们同样来实现fibo_snip1
中的代码。
首先,由于要使用ALU模块,我们需要定义好相关的变量,然后接着调用ALU,实现代码如下:
x1reg [5:0] a;
2reg [5:0] b;
3wire [2:0] f;
4
5parameter OP_ADD 3'b001;
6
7ALU FIB(a, b, OP_ADD, f, fn);
接着我们需要处理fn的递归生成了。但是首先来实现rst
的功能:
xxxxxxxxxx
61always@(posedge clk, negedge rst) begin
2 if(rst) begin
3 a f0;
4 b f1;
5 end
6end
当rst为假的时候,我们需要让a = f0; b = f1;
以此达到重置的效果。接下来就要处理a,b值的轮换了。
xxxxxxxxxx
91always@(posedge clk, negedge rst) begin
2 if(rst) begin
3 a f0;
4 b f1;
5 end else begin
6 a b;
7 b fn;
8 end
9end
当rst信号无效的时候,此时a = b; b = fn
实现了a,b 值的轮换。
至此,基于ALU的Fibonacci数列求解问题解决!
仿真/下载
ALU
仿真:
下载:
基于ALU的Fibonacci数列求解
仿真:
下载:
结果分析
ALU
资源使用情况:
Resource Utilization Available percentage LUT 28 63400 0.06 IO 24 210 9.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数列
资源使用情况:
Resource Utilization Available percentage LUT 38 63400 0.06 FF 24 126800 0.02 IO 20 210 9.52 BUFG 1 32 3.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
设计代码
xxxxxxxxxx
481module ALU(
2input [5:0] a,
3input [5:0] b,
4input [2:0] s,
5output [2:0] f,
6output reg [5:0] y
7);
8parameter OP_ADD 3'b001;
9parameter OP_SUB 3'b010;
10parameter OP_AND 3'b100;
11parameter OP_OR 3'b101;
12parameter OP_NOT 3'b110;
13parameter OP_XOR 3'b111;
1415// f: CF, V, Z
16reg CF 0, V 0, Z 0;
17initial begin
18y 0;
19end
20always@()
21begin
22case(s)
23OP_ADD:
24{CF, y} a b;
25OP_SUB:begin
26y a b;
27if(a < b) CF 1;
28else CF 0;end
29OP_AND:
30y a b;
31OP_OR:
32y a b;
33OP_NOT:
34y a;
35OP_XOR:
36y a b;
37default:begin
38y 0;
39CF 0;
40V 0;
41Z 0;
42end
43endcase
44Z (y 0);
45end
46assign f {CF, CF, Z};
4748endmodule
测试代码
xxxxxxxxxx
341module ALU_SIM(
2
3);
4// inputs
5reg [5:0] a, b;
6reg [2:0] s;
78//outputs
9wire [2:0] f;
10wire [5:0] y;
1112ALU ALU_INS(a, b, s, f, y);
13initial begin
14s 3'b001;
15a 60;
16b 2;
17#10; b 10;
18#10;
19s 3'b010;
20a 20;
21b 12;
22#10; b 30;
23#10;
24s 3'b100;
25a 10;
26b 49;
2728#10 s 3'b101;
29#10 s 3'b110;
30#10 s 3'b111;
31#10;
32;
33end
34endmodule
Fibonacci
设计代码
xxxxxxxxxx
311module fib(
2input [5:0] f0,
3input [5:0] f1,
4input rst,
5input clk,
6output [5:0] fn
7);
8reg [5:0] a;
9reg [5:0] b;
10wire [2:0] f;
11wire [5:0] out;
12// assign y = out;
13initial begin
14a 0;
15b 0;
16end
17parameter OP_ADD 3'b001;
18ALU FIB(a, b, OP_ADD, f, fn);
19// assign fn = out;
2021always@(posedge clk, negedge rst) begin
22if(rst) begin
23a f0;
24b f1;
25end else
26begin
27a b;
28b fn;
29end
30end
31endmodule
仿真代码
xxxxxxxxxx
181module fib_tb();
2reg [5:0] f0, f1;
3reg rst, clk;
4wire [5:0] fn;
5fib fib_tb(f0, f1, rst, clk, fn);
6initial begin
7clk 0;
8forever #10 clk clk;
9end
10initial begin
11rst 1;
12f0 1;
13f1 2;
14#3 rst 0;
15#3 rst 1;
16end
1718endmodule