红绿灯控制实验报告.docx
《红绿灯控制实验报告.docx》由会员分享,可在线阅读,更多相关《红绿灯控制实验报告.docx(39页珍藏版)》请在冰点文库上搜索。
红绿灯控制实验报告
计算机专业类课程
实验报告
日 期:
2019年6月 29 日
实验一
1、实验名称:
红绿灯控制
2、实验学时:
4
3、实验内容和目的:
•实验内容:
根据图3-1所示的电路控制表设计一个控制电路,使其能够通过改变开关控制红色、黄色、绿色三种颜色的灯的亮灭。
•实验目的:
熟悉集成开发系统与VerilogHDL硬件描述语言,能够编写简单的控制电路代码并在开发板上实现。
图3-1电路控制信号表
4、实验原理:
在XilinxISEDesignSuite14.7集成开发系统上创建Verilog模板,并使用VerilogHDL编写模板。
主要使用了assign赋值语句和算数和逻辑操作语句。
最后根据开发板上对应操作按钮编写约束并在开发板上生成。
5、实验器材(设备、元器件)
•PC计算机:
XilinxISEDesignSuite14.7集成开发系统、digilent.adept.system_v2.10.2.exe
•FPGA数字电路开发平台:
Anvyl(燧石TM)开发板
6、实验步骤:
1)推算红黄绿灯的控制逻辑和开关0,1的逻辑表达式为
a)Red=switch1^switch2
b)Green=switch1^switch2
c)Yellow=~(switch1^switch2)
2)创建模块单元接口,并设置好输入输出线路,这里为两个input,三个output
3)编写相关代码逻辑(这里对异或门进行优化)
modulelights(inputA,B,outputR,G,Y);
assignR=(A&~B)|(~A&B);
assignG=R;
assignY=~R;
endmodule
4)检验RTL电路
5)进行仿真测试:
◦试代码如下,测试逻辑见代码注释
initialbegin
//初始A均设置为0,此时应该黄灯亮
A=0;
B=0;
//250纳秒后,B为1,这个时候红绿灯亮
#250;
B=1;
//250纳秒后,A为1,B为0,这个时候红绿灯亮
#250;
A=1;
B=0;
//250秒后,A为1,B为1,这个时候黄灯亮
#250;
B=1;
end
◦仿真测试结果如下(图片较长,请放大查看看)
6)真机测试:
◦将A与B分别映射到开发板的V5和U4上。
◦RGB分别映射到开发板的T8R7U6上
(按下V5或U4)红绿灯亮(同时(不)按V5和U4)黄灯亮
7、实验结论、心得体会和改进建议:
•结论:
初步了解了Verilog的使用和简易的逻辑运算在电路中的实现原理。
•心得体会:
异或运算拥有三级门延迟,速度较慢,这里可以通过与或非门进行优化,使得延迟降低到2级门。
实验二
1、实验名称:
单周期CPU设计计算部分实现
2、实验学时:
4
3、实验内容和目的:
•实验内容:
使用特定的开发平台和开发板设计并实现CPU中的一些基本部件:
32位二选一多路选择器、5位二选一多路选择器、32位寄存器堆、ALU和(无)符号扩展器。
•实验目的:
熟悉组成CPU的基本部件和CPU的基本结构,能够设计相关基本器件。
4、实验原理:
•32位二选一多路选择器根据sel命令分别对32位的两个传入数据A和B进行选择,输出其中一个数据。
其逻辑结构如下。
图4-1二选一多路选择器的RTL图
•32位寄存器堆由32个32位寄存器组成,其功能是根据时序电路对数据进行存入和读出指定寄存器数据的操作。
其逻辑结构如下
寄存器堆的逻辑结构图(源计组PPT)
32位寄存器堆的RTL图
•ALU是CPU中重要的运算器,它可以根据ALU_op的3位控制命令对传入的两个数据进行加、减、与、或等运算。
ALU的逻辑结构图(源计组PPT)
ALU的RTL结构
定义的ALU_Ctr指令
•扩展器是CPU在进行I型指令等操作时的重要部件,其功能是根据传入的16位数据的最高位对其进行符号扩展或无符号扩展为32位的立即数,并将其输出。
这里原本给定的是符号扩展器,但是对于ori操作对于立即数进行的是无符号扩展(且ROM里面有此指令),故这里修改为通用扩展器。
图4-4符号扩展器的逻辑结构图
5、实验器材(设备、元器件)
•PC计算机:
XilinxISEDesignSuite14.7集成开发系统、digilent.adept.system_v2.10.2.exe
•FPGA数字电路开发平台:
Anvyl(燧石TM)开发板
6、实验步骤:
1、32位2选1选择器:
•根据其结构推断32位2选1选择器需要的线路
•根据逻辑编写相关代码
moduleMUX32_2_1(
input[31:
0]A,B,
inputsel,
output[31:
0]O
);
assignO=sel?
B:
A;
endmodule
•查看32位2选1选择器的RTL结构图(见上图)
•测试:
略,实现比较简单,暂时不需要测试
2、寄存器堆:
•设计寄存器堆的逻辑结构:
◦根据计组PPT提供的原理和结构图,确定寄存器堆的输入和输出的接口。
◦布置相关的寄存器(这里用32位的数组进行替代),并对其进行初始化。
◦定义输入数据源与寄存器的写入逻辑
◦定义相关的输出接口A和B与数据源的线路连接关系。
•编写相关的代码(实现逻辑见备注):
moduleRegFile(
input[4:
0]Rn1,Rn2,Wn,
inputWrite,Clock,
input[31:
0]Wd,
output[31:
0]Out1,Out2
);
//创建32个长度为32位的数组模拟寄存器堆
reg[31:
0]Register[1:
31];
//Out1输出Rn1信号指定的寄存器
assignOut1=(Rn1==0)?
0:
Register[Rn1];
//Out2输出Rn2信号指定的寄存器
assignOut2=(Rn2==0)?
0:
Register[Rn2];
//当始处于时钟上升沿并且处于写使能的时候,向寄存器堆里面写入数据
always@(posedgeClock)begin
if((Write)&&(Wn!
=0))Register[Wn]<=Wd;
end
//堆寄存器堆里面的数据进行初始化(全0)
integeri;
initialbegin
for(i=1;i<=31;i=i+1)Register[i]=0;
end
endmodule
•测试寄存器堆:
◦RTL图如下(图片较小,请放大查看):
•编写相关仿真代码:
◦仿真测试逻辑,每间隔100纳秒,向寄存器堆里写入指定数据,并且不断更新Rn1和Rn2的值,观察out1和out2的输出结果。
alwaysbegin
#400;
//要写入的寄存器编号,每隔400纳秒,要写入的目标寄存器编号加1
Wn=Wn+1;
//这里将写入的Wd取值为4倍的Wn的值
//声明一个Temp临时变量用于0扩展
temp={28'h0,Wn};
Wd={temp[29:
0],2'b00};
//输出端口A,B指定的目标寄存器的编号+1
Rn1=Rn1+1;
Rn2=Rn2+1;
end
alwaysbegin
#100;
Clock=~Clock;
Write=Clock==1?
1:
0;
end
•校验仿真测试结果(图片较长,请放大查看):
◦为了方便查看,这里将结果转化位16进制。
◦由图1可知,Rn1和Rn2增加正常,Out1与out2输出的结果与寄存器堆里的指定Rn编号相符,即说明输出结果正确。
◦由图2可知,寄存器堆里存放的数据满足Wd=4*Wn,说明写入正确并且数据得到了顺利的保存。
图1仿真结果
图2寄存器堆的里存放的数据
3、通用扩展器
•通用扩展器的实现逻辑相对较为简单,故这里只放出实现的代码
moduleExtender(
input[15:
0]a,
inputExtOP,
output[31:
0]b);
assignb=ExtOP?
{a[15]?
16'hffff:
16'h0,a}:
{a[15]?
16'h0000:
16'h0,a};
endmodule
4、ALU
•设计ALU的逻辑结构
◦根据计组教材PPT提供的原理结构图,确定ALU的输入和输出的接口
◦参考老师提供的指令ROM提供的指令,根据实际情况,确定ALUCtr对应的相关操作。
•编写相关代码:
`defineADD3'b000
`defineSUB3'b100
`defineAND3'b001
`defineOR3'b010
`defineXOR3'b101
`defineLUI3'b110
moduleALU(
input[31:
0]A,B,
input[2:
0]ALU_Ctr,
outputreg[31:
0]Result,
outputregZero);
always@(AorBorALU_Ctr)
begin
case(ALU_Ctr)
`ADD:
Result=A+B;
`SUB:
Result=A-B;
`AND:
Result=A&B;
`OR:
Result=A|B;
`XOR:
Result=A^B;
`LUI:
Result=B<<16;
default:
Result=32'h00000000;
endcase
Zero=~|Result;
end
endmodule
•测试ALU
•ALU的RTL结构图如下(图片较小,请放大查看):
•编写ALU的仿真测试代码(详细测试内容见注释):
initialbegin
A=32'h000000ff;
B=32'h000000cc;
ALU_Ctr=111;//初始为111,此时返回全0
#100;
ALU_Ctr=3'b000;//测试加法
#100;
ALU_Ctr=3'b100;//测试减法
#100;
ALU_Ctr=3'b001;//测试与
#100;
ALU_Ctr=3'b101;//测试或
#100;
ALU_Ctr=3'b010;//测试异或
#100;
ALU_Ctr=3'b110;//测试B的左移16位
#100;
B=32'h000000ff;
ALU_Ctr=3'b100;//测试0标志位
end
•检验ALU仿真测试结果(图片较长,请放大查看):
◦为了方便查看,这里将结果转化为16进制
◦
由下图和上面相关测试数据对比可知,上述的相关操作均能够通过测试。
七、实验结论、心得体会和改进建议:
心得:
•做实验千万不要一味的抄老师的代码,之前PPT里面的代码是几个版本的结合体,实际上不互相兼容,这也是之前调不出来的主要原因。
ALU所做的所有操作应当结合指令ROM和控制单元,而不是单纯的抄写计组书上面的MIPSCPU的操作逻辑。
实验三
一、实验名称:
单周期CPU的设计与实现
二、实验学时:
4
三、实验内容和目的:
•实验内容:
要求对单周期CPU中控制器进行设计与实现,主要包括Control部件和ALU_Ctr部件。
•实验目的:
了解CPU中控制器部件的工作原理,能够熟练使用系统开发平台对于设计的控制电路进行仿真与实现,最后能够将部件进行封装。
四、实验原理:
•本次实验要实现的是基于MIPS指令集的单周期CPU,其中控制单元如图4-1所示,包括两部分:
Control部件和ALU_CTR部件。
当MIPS指令类型为R型时,op为000000,指令功能由输入进ALU_CTR部件的func指令字段控制。
当MIPS指令类型为I型和J型时,指令的功能由op字段控制。
图4-1控制器单元的结构图
•Control部件和ALU_CTR部件的设计要能够满足MIPS中的三种指令,其控制字段与指令的关系如图所示:
Control部件中输入与输出的关系(源计组ppt)
•根据给出的关系图得出控制信号的逻辑表达式,在集成开发系统上进行编程和仿真并在开发板上进行实现,最后对控制电路进行封装形成Control_Unit。
五、实验器材(设备、元器件)
•PC计算机:
XilinxISEDesignSuite14.7集成开发系统、digilent.adept.system_v2.10.2.exe
•FPGA数字电路开发平台:
Anvyl(燧石TM)开发板
六、实验步骤:
(一)Control:
•根据计组PPT上面op指令中非R型指令的部分的指令特征以及对应的信号确定Control负责的功能。
•参照上图中给定的控制单元的结构分析Control单元输入和输出的接口
•根据指令ROM中的指令,确定哪些指令会用得到(比如上图并未提供Jump信号的接口但是实际上却用到了,故还需要添加Jump信号的接口)
•参考计组PPT确定Control输出信号的组合逻辑(原理如下)
•根据上面确定的组合逻辑,编写Control部分的代码
moduleControl(
input[5:
0]op,
outputRegDst,RegWrite,ALUSrc,
outputMemWrite,MemtoReg,
outputBranch,Jump,ExtOP,
output[2:
0]ALU_op,R_type);
wirei_Rt=~|op;
wirei_lw=op[5]&~op[4]&~op[3]&~op[2]&op[1]&op[0];
wirei_sw=op[5]&~op[4]&~op[3]&op[2]&~op[1]&op[0];
wirei_beq=op[5]&op[4]&op[3]&op[2]&~op[1]&~op[0];
wirei_ori=~op[5]&~op[4]&op[3]&op[2]&~op[1]&op[0];
wirei_jump=~op[5]&~op[4]&~op[3]&~op[2]&op[1]&~op[0];
assignRegDst=i_Rt;
assignRegWrite=i_Rt|i_lw|i_ori;
assignALUSrc=i_lw|i_sw|i_ori;
assignMemWrite=i_sw;
assignMemtoReg=i_lw;
assignBranch=i_beq;
assignJump=i_jump;
assignExtOP=~i_ori;
assignALU_op[2]=i_beq;
assignALU_op[1]=i_ori;
assignALU_op[0]=0;
assignR_type=i_Rt;
endmodule
(二)AlU_OP
•根据计组PPT上给定的ALU_OP结构,确定ALU_OP所需要的接口
•根据R型指令对于的ALT_Ctr编写对应的逻辑
◦由于7条指令系统中只有add(000)和sub(100)两条R型指令
◦故实际上只需满足以下条件即可:
ALUctr<0>=0
ALUctr<1>=0
ALUctr<2>=func<1>
•ALU_OP实现代码如下:
moduleALUop(
input[5:
0]func,
output[2:
0]ALU_op);
assignALU_op[0]=0;
assignALU_op[1]=0;
assignALU_op[2]=func[1];
endmodule
(三)ControlUnit的封装:
•ControlUnit的整体结构如图所示:
•故这里需要一个二选一选择器将2者连接,代码如下
moduleControl_Unit(
input[5:
0]op,func,
outputRegDst,RegWrite,ALUSrc,
outputMemWrite,MemtoReg,
outputBranch,Jump,ExtOP,
output[2:
0]ALU_ctr);
wire[2:
0]ALU_op1;
wire[2:
0]ALU_op2;
wireR_type;
ControlU0(.op(op),.RegDst(RegDst),.RegWrite(RegWrite),
.ALUSrc(ALUSrc),.MemWrite(MemWrite),.MemtoReg(MemtoReg),
.Branch(Branch),.Jump(Jump),.ExtOP(ExtOP),.ALU_op(ALU_op1),
.R_type(R_type));
ALUopU1(.func(func),.ALU_op(ALU_op2));
//这里根据是否是R型指令对ALUctr进行选择输出
assignALU_ctr=R_type?
ALU_op2:
ALU_op1;
endmodule
•ControlUnit整体的RTL图:
•ALU_OP的整体RTL图:
•Control部分的RTL图(图片过长,请放大查看):
•测试:
由于单独测试控制单元相对来说比较麻烦,故这里放在后面测试MIPS_CPU的时候一起测试。
七、实验结论、心得体会和改进建议:
心得:
•做实验的时候千万不能一味的抄去PPT上面的代码,应该结合实际功能和场景去理解并设计。
比如说这里的ControlUnit并没有提供Jump信号,但是实际上指令ROM里面的第一条就是Jump指令,所以需要手动添加。
•某一个模块在仿真的时候过了并不代表数据正确了,也不代表连接了其他的模块就能够正常工作,比如说老师给的扩展器实际上仅仅为符号扩展器,但是在做ori指令的时候需要做无符号的扩展,所以应当在控制单元里面输出一个ExtOP信号,来保证数据的正确性。
当然不这么做仿真跑出来任然有数据且一片绿,但是实际上数据是错误的。
•在编写Control的时候应当严谨,保证输入的op能够正确的对应到ALU的控制信号和其他控制信号上,因为一般来说只要接上线了就会有数据,但是实际上很有可能op或func对应的控制信号是错误的,但是仿真跑出来任是一片绿色,这些问题就只能够通过人工手动调试一一检查才能够找的出来。
!
!
!
改进建议:
•强烈要求教一下如何使用Verilog如何DEBUG,调试ControlUnit踩了不少的坑。
实验四
一、实验名称:
单周期CPU的设计与实现
二、实验学时:
4
三、实验内容和目的:
•实验内容:
设计并实现Fetch部件,即取值电路部件。
对之前实验中设计的部件按照单周期计算机CPU结构进行封装。
最终实现可运行的MIPSCPU。
•实验目的:
了解并掌握基于MIPS指令集的单周期计算机CPU的结构和工作原理,可以根据单周期计算机结构图和MIPS指令集的相关知识设计并实现一个单周期计算机的CPU。
四、实验原理:
•对取值电路即Fetch部分电路进行封装
•对MIPSCPU按照单周期计算机结构图进行封装。
•将CPU,RAM,ROM,SEG,AN等组件封装为一个SOC
图4-1单周期计算机结构图
五、实验器材(设备、元器件)
•PC计算机:
XilinxISEDesignSuite14.7集成开发系统、digilent.adept.system_v2.10.2.exe
•FPGA数字电路开发平台:
Anvyl(燧石TM)开发板
六、实验步骤:
1、设计取址电路Fetch:
•根据计组PPT提供的Fetch模块的结构与所学Fetch的功能,分析Fetch所需要的接口。
•根据Fetch的输出的不同指令类型和输入的不同信号,将其拆分为多个内部元件来完成不同地址的生成。
•分析Fetch输入的控制信号,确定内部元件之间接口如何连接
•Fetch的相关代码(各个组件功能见注释):
moduleFetch(
inputReset,Clock,Jump,Branch,Zero,
input[31:
0]br_imm,Instruction,
output[31:
0]addr);
wire[31:
0]pc_plus4,br_imm_ext,br_addr_extra,
br_addr_result,jump_addr_result,next_pc;
wire[1:
0]select;
//由输入的信号确定选择信号
assignselect=(Jump)?
2'b10:
(Branch&Zero)?