[转帖]DE2_115_Digital_Logic Lab1

Introduction

这个练习的目的是学习如何连接简单的输入、输出设备到一个FPGA芯片,并且用这些器件实现一个电路。我们将用DE2开发板上的switches SW17-0作为输入,用LED和7-segment displays作为输出。

完成DE2 实验练习1(Digital Logic)对与初学者来说是一个比较大的实验。我估计,每天要花几小时才能完成。这个实验包括6个部分,主要是组合逻辑电路和使用assign语句

Part I :第一次使用assign语句

Altera 的DE2开发板有18个拨动开关(toggle switch)和18个红色的LED。Part I非常简单,在实验手册里首先介绍了Verilog的格式,并给出了代码。需要自己做的部分就是把代码粘贴到Quartus II然后运行。当你拨动一个开关(比如Switch 1),对应的LED就会亮(比如LEDR1),这部分在实验手册里解释的很详细。

/***************Part1***************/

module lab1(SW,LEDR);
input[17:0] SW;
output[17:0] LEDR;

assign LEDR=SW;

endmodule

Part II:设计一个8位的2选1多路选择器

用Verilog设计一个多路选择器有很多种方法。但是在这个实验里,要求只能用门级电路描述。比如:assign m=(~s&x)|(s&y);这里x和y是输入,s是选择信号,m是输出。X被定义为SW 0到7,Y被定义为SW 8到15,S被定义为SW17,M被定义为绿色的LEDG 0到7.这部分的完整代码如下。

 /***************Part2***************/

module lab1(LEDR,LEDG,SW);
input[17:0] SW;
output[17:0] LEDR;
output[7:0] LEDG;
wire S;
wire[7:0] X,Y,M;
assign S=SW[17];
assign X=SW[7:0];
assign Y=SW[15:8];
assign LEDR=SW;
assign LEDG=M;

mux2to1 m7(S,X[7],Y[7],M[7]);
mux2to1 m6(S,X[6],Y[6],M[6]);
mux2to1 m5(S,X[5],Y[5],M[5]);
mux2to1 m4(S,X[4],Y[4],M[4]);
mux2to1 m3(S,X[3],Y[3],M[3]);
mux2to1 m2(S,X[2],Y[2],M[2]);
mux2to1 m1(S,X[1],Y[1],M[1]);
mux2to1 m0(S,X[0],Y[0],M[0]);

endmodule


module mux2to1(s,x,y,m);
input x,y,s;
output m;

assign m=(~s&x)|(s&y);

endmodule

代码里,有一个小技巧。我把RTL代码分成2部分。1个主模块和1个多路选择器模块。通过调用多选器模块,可以很容易的实现设计。

Part III:设计一个3位的5选一多路选择器

/***************Part III***************/

module lab1(SW,LEDR,LEDG);
input[17:0] SW;
output[17:0] LEDR;
output[2:0] LEDG;
wire[2:0]s,u,v,w,x,y;
wire[2:0] m;
wire[2:0] m0,m1,m2;
assign LEDR=SW;

assign s=SW[17:15];
assign u=SW[14:12];
assign v=SW[11:9];
assign w=SW[8:6];
assign x=SW[5:3];
assign y=SW[2:0];
assign LEDG=m;

assign m0[0]=(~s[0]&u[0])|(s[0]&v[0]);
assign m0[1]=(~s[0]&u[1])|(s[0]&v[1]);
assign m0[2]=(~s[0]&u[2])|(s[0]&v[2]);

assign m1[0]=(~s[0]&w[0])|(s[0]&x[0]);
assign m1[1]=(~s[0]&w[1])|(s[0]&x[1]);
assign m1[2]=(~s[0]&w[2])|(s[0]&x[2]);

assign m2[0]=(~s[1]&m0[0])|(s[1]&m1[0]);
assign m2[1]=(~s[1]&m0[1])|(s[1]&m1[1]);
assign m2[2]=(~s[1]&m0[2])|(s[1]&m1[2]);

assign m[0]=(~s[2]&m2[0])|(s[2]&y[0]);
assign m[1]=(~s[2]&m2[1])|(s[2]&y[1]);
assign m[2]=(~s[2]&m2[2])|(s[2]&y[2]);

endmodule

part IV:设计一个7segment 显示“HELLO”

这部分要求用一个7segment显示H、E、L、O。需要注意DE2上的七段码数码管是共阴极,对应的真值表见表 1 7-segment 译码真值表:

c2c1c0

character

7_segment

000

H

1001000

001

E

0110000

010

L

1110001

011

O

0000001

100

blank

1111111

101

110

111

表 1 7-segment 译码真值表

表达式化简,用卡诺图,比如seg[6](上表7-segment的最右边的一列),化简过程如下图所示:

/***************Part IV***************/

module lab1(SW,LEDR,HEX0);
input[2:0] SW;
output[2:0] LEDR;
output[0:6] HEX0;
assign LEDR=SW;
// seven segment decoder for "HELO"
assign HEX0[0] = SW[2]|~SW[0];
assign HEX0[1]=SW[2]|(SW[1]&~SW[0])|(~SW[1]&SW[0]);
assign HEX0[2]=SW[2]|(SW[1]&~SW[0])|(~SW[1]&SW[0]);
assign HEX0[3] = SW[2]|(~SW[1]&~SW[0]);
assign HEX0[4] = SW[2];
assign HEX0[5] = SW[2];
assign HEX0[6] = SW[2]|SW[1];
endmodule

注:因为要求用连续赋值语句和布尔逻辑实现,对于七段码的每一段的表达式都可以根据真值表先化简(当然综合工具会自动化简,但是如果考综合工具化简,每个表达式就会很长)。化简就会用到我们学过的卡诺图图(以前一直觉得卡诺图用不上L)。

Part V:用5个7segment循环显示HELLO

这部分要求用5个数码管循环显示HELLO,涉及part III和part IV的引用。5个数码管循环显示如图2.

/***************Part V***************/

module lab1(SW,HEX4,HEX3,HEX2,HEX1,HEX0);
input[17:0] SW;
output[0:6] HEX4,HEX3,HEX2,HEX1,HEX0;
wire[2:0] M4,M3,M2,M1,M0;

mux_3bit_5to1 N4(SW[17:15],SW[14:12],SW[11:9],SW[8:6],SW[5:3],SW[2:0],M4);
mux_3bit_5to1 N3(SW[17:15],SW[11:9],SW[8:6],SW[5:3],SW[2:0],SW[14:12],M3);
mux_3bit_5to1 N2(SW[17:15],SW[8:6],SW[5:3],SW[2:0],SW[14:12],SW[11:9],M2);
mux_3bit_5to1 N1(SW[17:15],SW[5:3],SW[2:0],SW[14:12],SW[11:9],SW[8:6],M1);
mux_3bit_5to1 N0(SW[17:15],SW[2:0],SW[14:12],SW[11:9],SW[8:6],SW[5:3],M0);

char_7seg H4(M4,HEX4);
char_7seg H3(M3,HEX3);
char_7seg H2(M2,HEX2);
char_7seg H1(M1,HEX1);
char_7seg H0(M0,HEX0);

endmodule

module char_7seg(SW,HEX);
input[2:0] SW;
output[0:6] HEX;
assign HEX[0] = SW[2]|~SW[0];
assign HEX[1] = SW[2]|(SW[1]&~SW[0])|(~SW[1]&SW[0]);
assign HEX[2] = SW[2]|(SW[1]&~SW[0])|(~SW[1]&SW[0]);
assign HEX[3] = SW[2]|(~SW[1]&~SW[0]);
assign HEX[4] = SW[2];
assign HEX[5] = SW[2];
assign HEX[6] = SW[2]|SW[1];
endmodule

module mux_3bit_5to1(s,u,v,w,x,y,m);
//input[17:0] SW;
//output[17:0] LEDR;
//output[2:0] LEDG;
input[2:0]s,u,v,w,x,y;
output[2:0] m;
wire[2:0] m0,m1,m2;
//assign LEDR=SW;

//assign s=SW[17:15];
//assign u=SW[14:12];
//assign v=SW[11:9];
//assign w=SW[8:6];
//assign x=SW[5:3];
//assign y=SW[2:0];
//assign LEDG=m;

assign m0[0]=(~s[0]&u[0])|(s[0]&v[0]);
assign m0[1]=(~s[0]&u[1])|(s[0]&v[1]);
assign m0[2]=(~s[0]&u[2])|(s[0]&v[2]);

assign m1[0]=(~s[0]&w[0])|(s[0]&x[0]);
assign m1[1]=(~s[0]&w[1])|(s[0]&x[1]);
assign m1[2]=(~s[0]&w[2])|(s[0]&x[2]);

assign m2[0]=(~s[1]&m0[0])|(s[1]&m1[0]);
assign m2[1]=(~s[1]&m0[1])|(s[1]&m1[1]);
assign m2[2]=(~s[1]&m0[2])|(s[1]&m1[2]);

assign m[0]=(~s[2]&m2[0])|(s[2]&y[0]);
assign m[1]=(~s[2]&m2[1])|(s[2]&y[1]);
assign m[2]=(~s[2]&m2[2])|(s[2]&y[2]);

endmodule

Part VI:用8个数码管循环显示HELLO

要求按照图 3 数码管循环显示,这是整个实验最复杂的部分,需要用到前5部分的信息。因为要用到选择信号的8中状态,需要创建一个8选1的多路选择器。其余就类似第5部分。注意在实例引用8选1多路器时8个输入信号的排列(我的神啊,眼睛差点都看花了J)!!

/***************Part VI***************/ 

module lab1(SW,HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0);
input[17:0] SW;
output[0:7] HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0;
wire[2:0] M7,M6,M5,M4,M3,M2,M1,M0;

mux_3bit_8to1 N7(SW[17:15],SW[2:0],SW[2:0],SW[2:0],SW[14:12],SW[11:9],SW[8:6],SW[8:6],SW[5:3],M7);
mux_3bit_8to1 N6(SW[17:15],SW[2:0],SW[2:0],SW[14:12],SW[11:9],SW[8:6],SW[8:6],SW[5:3],SW[2:0],M6);
mux_3bit_8to1 N5(SW[17:15],SW[2:0],SW[14:12],SW[11:9],SW[8:6],SW[8:6],SW[5:3],SW[2:0],SW[2:0],M5);
mux_3bit_8to1 N4(SW[17:15],SW[14:12],SW[11:9],SW[8:6],SW[8:6],SW[5:3],SW[2:0],SW[2:0],SW[2:0],M4);
mux_3bit_8to1 N3(SW[17:15],SW[11:9],SW[8:6],SW[8:6],SW[5:3],SW[2:0],SW[2:0],SW[2:0],SW[14:12],M3);
mux_3bit_8to1 N2(SW[17:15],SW[8:6],SW[8:6],SW[5:3],SW[2:0],SW[2:0],SW[2:0],SW[14:12],SW[11:9],M2);
mux_3bit_8to1 N1(SW[17:15],SW[8:6],SW[5:3],SW[2:0],SW[2:0],SW[2:0],SW[14:12],SW[11:9],SW[8:6],M1);
mux_3bit_8to1 N0(SW[17:15],SW[5:3],SW[2:0],SW[2:0],SW[2:0],SW[14:12],SW[11:9],SW[8:6],SW[8:6],M0);

char_7seg H7(M7,HEX7);
char_7seg H6(M6,HEX6);
char_7seg H5(M5,HEX5);
char_7seg H4(M4,HEX4);
char_7seg H3(M3,HEX3);
char_7seg H2(M2,HEX2);
char_7seg H1(M1,HEX1);
char_7seg H0(M0,HEX0);

endmodule

module mux_3bit_8to1(s,u,v,w,x,y,a,b,c,m);
//input[17:0] SW;
//output[17:0] LEDR;
//output[2:0] LEDG;
input[2:0]s,u,v,w,x,y,a,b,c;
output[2:0] m;
wire[2:0] m0,m1,m2,m3,m4,m5;
//assign LEDR=SW;
//assign s=SW[17:15];
//assign u=SW[14:12];
//assign v=SW[11:9];
//assign w=SW[8:6];
//assign x=SW[5:3];
//assign y=SW[2:0];
//assign LEDG=m;

assign m0[0]=(~s[0]&u[0])|(s[0]&v[0]);
assign m0[1]=(~s[0]&u[1])|(s[0]&v[1]);
assign m0[2]=(~s[0]&u[2])|(s[0]&v[2]);

assign m1[0]=(~s[0]&w[0])|(s[0]&x[0]);
assign m1[1]=(~s[0]&w[1])|(s[0]&x[1]);
assign m1[2]=(~s[0]&w[2])|(s[0]&x[2]);

assign m2[0]=(~s[0]&y[0])|(s[0]&a[0]);
assign m2[1]=(~s[0]&y[1])|(s[0]&a[1]);
assign m2[2]=(~s[0]&y[2])|(s[0]&a[2]);

assign m3[0]=(~s[0]&b[0])|(s[0]&c[0]);
assign m3[1]=(~s[0]&b[1])|(s[0]&c[1]);
assign m3[2]=(~s[0]&b[2])|(s[0]&c[2]);

assign m4[0]=(~s[1]&m0[0])|(s[1]&m1[0]);
assign m4[1]=(~s[1]&m0[1])|(s[1]&m1[1]);
assign m4[2]=(~s[1]&m0[2])|(s[1]&m1[2]);

assign m5[0]=(~s[1]&m2[0])|(s[1]&m3[0]);
assign m5[1]=(~s[1]&m2[1])|(s[1]&m3[1]);
assign m5[2]=(~s[1]&m2[2])|(s[1]&m3[2]);

assign m[0]=(~s[2]&m4[0])|(s[2]&m5[0]);
assign m[1]=(~s[2]&m4[1])|(s[2]&m5[1]);
assign m[2]=(~s[2]&m4[2])|(s[2]&m5[2]);

endmodule

module char_7seg(SW,HEX);
input[2:0] SW;
output[0:6] HEX;
assign HEX[0] = SW[2]|~SW[0];
assign HEX[1] = SW[2]|(SW[1]&~SW[0])|(~SW[1]&SW[0]);
assign HEX[2] = SW[2]|(SW[1]&~SW[0])|(~SW[1]&SW[0]);
assign HEX[3] = SW[2]|(~SW[1]&~SW[0]);
assign HEX[4] = SW[2];
assign HEX[5] = SW[2];
assign HEX[6] = SW[2]|SW[1];
endmodule

注:3位8选1多路器的设计思想如同前面的3位5选1多路器的设计思想一致。在这部分,我预选设置SW的值如表2。

SW

预设值

数码管显示

SW14-12

000

H

SW11-9

001

E

SW8-6

010

L

SW5-3

011

O

SW2-0

100

blank

Conclusion

整体来看,Altera的实验设计很花心思。在实验1,主要要求用基本的布尔逻辑实现。不允许用高级的RTL描述,考查门级电路实现(心中有电路图,描述就不难。J)。完成整个实验非常有趣,积累基本经验,并且回顾和更好的理解底层的数字逻辑设计。

原文地址:https://www.cnblogs.com/spartan/p/2025217.html