目录
1、放置2个2-4译码器模块,则总共有2组SW, 每组2个,2组LED,每组4个,每组SW分别控 制其对应的LED组。
2、参照代码,设计一个3-8译码器,完成类似的拨码开关实验。注意代码中的信号宽度设定。
3、自行查阅手册中的7段译码器管脚对应关系, 用4个拨码开关控制一个7段译码器的数字,从 0-9-A-F,共16个数字和字母
1、参照代码,设计一个0-17的计数器,当计数值为17的时候,OV输出1,其他输出0, 注意设定合理的信号位宽。
2、针对以上计数器,修改输出逻辑,当计数值为0-8时,OV输出0,9-17时OV输出1
2、把计数器的0-15计数值经过译码,在DE0 的 HEX LED上显示成0-9-A-F的十六 进制数
3、修改时间基准发生器,设计一个使用2个HEX LED,精度为0.1秒,范围为0-9.9秒的计时秒表。
实验一 项目创建、编译和下载
学生实验:用1个拨码开关控制所有的LED灯亮灭
本题属于直接拼接,主要是熟悉操作。
电路连接:
管脚分配(与参考书中保持一致):
参考图 assigenment ——> pin planner中的设定
编译顺序(按顺序点击图标):
实验二 FPGA译码器组合逻辑
- 管脚配置:
如果使用固定的开发板进行开发,每次的工程配置都是一样的,通过“assignments->pin planner”手动设置会浪费不少时间。以下介绍一种方法,第一次手动正确配置之后可以用导入的方法。
1、选择Project->Generate Tcl File for Project,指定存放路径,选择保存选项,也可把Include default assignments选上。
2、打开生成的tcl文件,把前面的 Check that the right project is open 的代码用 # 注释掉,不然新建立的工程名要与 用来生成该tcl文件工程的工程名 相同才可以有效导入此tcl文件。
3、把步骤1中生成的.tcl文件放到新建的工程文件夹下(.qsf文件所在目录),选择Tools—>Tcl Scripts,选择这个.tcl文件并点击Run,就可以自动得到新的.qsf文件。
用文本的方式指派管脚
• 新建一个文本文件,例如 pin_de0.txt,内容的第一行是to, location 然后下面内容就是输出信号名称和管脚位置对应关系
• 通过Import assignments来把该文本文件导入
- 学生实验:
1、放置2个2-4译码器模块,则总共有2组SW, 每组2个,2组LED,每组4个,每组SW分别控 制其对应的LED组。
仪器放置:• 双击BDF文件中的空白处 • 添加2-4译码器
本题难度不大,只需要放置元器件,然后通过上述文本配置管脚的方法就可以了
管脚:
to, location
LED[7], PIN_C2
LED[6] , PIN_C1
LED[5] , PIN_E1
LED[4] , PIN_F2
LED[3] , PIN_H1
LED[2] , PIN_J3
LED[1] , PIN_J2
LED[0] , PIN_J1
SW3 , PIN_G4
SW2 , PIN_H6
SW1 , PIN_J6
SW0, PIN_H5
2、参照代码,设计一个3-8译码器,完成类似的拨码开关实验。注意代码中的信号宽度设定。
<1>增加译码器代码的方法:
(1)开始时直接添加:
(2) 新建项目之后添加
<2> 为代码文件创建符号:
• 该过程生成代码文件对应的符号模块 • 可以在BDF文件中调用
<3>创建电路图并生成
• 然后另存文件 • 注意文件名和顶层设计的名称保持一致
<4>管脚配置
to, location
LED[7], PIN_C2
LED[6] , PIN_C1
LED[5] , PIN_E1
LED[4] , PIN_F2
LED[3] , PIN_H1
LED[2] , PIN_J3
LED[1] , PIN_J2
LED[0] , PIN_J1
SW2 , PIN_H6
SW1 , PIN_H5
SW0, PIN_J6
<5> 编译,拨动开关检查
3、自行查阅手册中的7段译码器管脚对应关系, 用4个拨码开关控制一个7段译码器的数字,从 0-9-A-F,共16个数字和字母
7段译码器管脚对应关系:
module top416(
IN , // input
OUT ); // output
input [3:0] IN;
output[7:0] OUT;
reg [7:0] OUT;
// get the OUT
always @ (IN) begin
case(IN)
4'b0000: OUT = 8'b1100_0000;
4'b0001: OUT = 8'b1111_1001;
4'b0010: OUT = 8'b1010_0100;
4'b0011: OUT = 8'b11011_0000;
4'b0100: OUT = 8'b1001_1001;
4'b0101: OUT = 8'b1001_0010;
4'b0110: OUT = 8'b1000_0010;
4'b0111: OUT = 8'b1111_1000;
4'b1000: OUT = 8'b1000_0000;
4'b1001: OUT = 8'b1001_0000;
4'b1010: OUT = 8'b1000_1000;
4'b1011: OUT = 8'b1000_0011;
4'b1100: OUT = 8'b1100_0110;
4'b1101: OUT = 8'b1100_0001;
4'b1110: OUT = 8'b1000_0110;
4'b1111: OUT = 8'b1000_1110;
// full case 不需要写default,否则一定要有default
endcase
end
endmodule
管脚:
to, location
SW3,PIN_G4
SW2 , PIN_H6
SW1 , PIN_H5
SW0, PIN_J6
HEX0_D[0],PIN_E11
HEX0_D[1],PIN_F11
HEX0_D[2],PIN_H12
HEX0_D[3],PIN_H13
HEX0_D[4],PIN_G12
HEX0_D[5],PIN_F12
HEX0_D[6],PIN_F13
HEX0_D[7],PIN_D13
实验三 计数器、波形仿真、SignalTap
- SignalTap配置过程
(1)编译程序
(2)新建SignalTap
(3)配置
需要点击蓝色下降箭头
双击空白处添加
(4)编译和配置
学生实验
1、参照代码,设计一个0-17的计数器,当计数值为17的时候,OV输出1,其他输出0, 注意设定合理的信号位宽。
新建SignalTapII 文件前先连接开发板
module cnt_0to9(
CLK , // clock
CNTVAL, // counter value
OV ); // overflow
input CLK;
output [5-1:0] CNTVAL;
output OV;
reg [5-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(CNTVAL >= 17)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
always @ (CNTVAL) begin
if(CNTVAL == 17)
OV = 1'b1;
else
OV = 1'b0;
end
endmodule
2、针对以上计数器,修改输出逻辑,当计数值为0-8时,OV输出0,9-17时OV输出1
module cnt_0to9(
CLK , // clock
CNTVAL, // counter value
OV ); // overflow
input CLK;
output [5-1:0] CNTVAL;
output OV;
reg [5-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(CNTVAL >= 17)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
always @ (CNTVAL) begin
if(CNTVAL > 8 )
OV = 1'b1;
else
OV = 1'b0;
end
endmodule
if(CNTVAL > 8 )
OV = 1'b1;
else
OV = 1'b0;
必须这样写,要不无法识别
• 用SignalTap验证
尝试并思考,如果时钟是50MHz,把OV接到一个LED上,能看见什么现象,为什么?
如果时钟是50MHz,那么一个周期就是20ns,再执行上面的程序,也就是说LED灯会在9-17这个过程变亮,其余时间是灭的,但是亮的持续时间只有9*20=180ns,用肉眼分辨不出来,看到的是常亮的状态。
实验四 时间基准电路 和 带使能的多周期计数器
- 学生实验
1、参照代码,把后级计数器的计数范围改为0-15。
module start_lab(
CLK , // clock
CNTVAL, // counter value
OV ); // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 25_000_000;
reg [32-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
always @ (CNTVAL) begin
if(CNTVAL == MAX_VAL)
OV = 1'b1;
else
OV = 1'b0;
end
endmodule // module cnt_en_0to9
module cnt_en_0to15(
CLK , // clock
CNTVAL, // counter value
EN ,
OV ); // overflow
input CLK;
input EN;
output [4-1:0] CNTVAL;
output OV;
reg [4-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(EN) begin // work enable
if(CNTVAL >= 15)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
else
CNTVAL <= CNTVAL ; // hold same value
end
always @ (CNTVAL) begin
if(CNTVAL == 15)
OV = 1'b1;
else
OV = 1'b0;
end
endmodule // module cnt_en_0to15
2、把计数器的0-15计数值经过译码,在DE0 的 HEX LED上显示成0-9-A-F的十六 进制数
在原有的基础上添加一个译码器就可以了
module dec_4to16(
IN , // input
OUT ); // output
input [3:0] IN;
output[7:0] OUT;
reg [7:0] OUT;
// get the OUT
always @ (IN) begin
case(IN)
4'b0000: OUT = 8'b1100_0000; //0
4'b0001: OUT = 8'b1111_1001;//1
4'b0010: OUT = 8'b1010_0100;//2
4'b0011: OUT = 8'b11011_0000;//3
4'b0100: OUT = 8'b1001_1001;//4
4'b0101: OUT = 8'b1001_0010;//5
4'b0110: OUT = 8'b1000_0010;//6
4'b0111: OUT = 8'b1111_1000;//7
4'b1000: OUT = 8'b1000_0000;//8
4'b1001: OUT = 8'b1001_0000;//9
4'b1010: OUT = 8'b1000_1000;//A
4'b1011: OUT = 8'b1000_0011;//B
4'b1100: OUT = 8'b1100_0110;//c
4'b1101: OUT = 8'b1100_0001;//D
4'b1110: OUT = 8'b1000_0110;//E
4'b1111: OUT = 8'b1000_1110;//F
// full case 不需要写default,否则一定要有default
endcase
end
endmodule
管脚:
to, location
CLK50,PIN_G21
OV,PIN_B1
HEX0_D[0],PIN_E11
HEX0_D[1],PIN_F11
HEX0_D[2],PIN_H12
HEX0_D[3],PIN_H13
HEX0_D[4],PIN_G12
HEX0_D[5],PIN_F12
HEX0_D[6],PIN_F13
HEX0_D[7],PIN_D13
RTL图:
3、修改时间基准发生器,设计一个使用2个HEX LED,精度为0.1秒,范围为0-9.9秒的计时秒表。
4、自行设计上面计时器的附加控制功能(清零、暂 停)。
module cnt_sync(
CLK , // clock
CNTVAL, // counter value
OV ); // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 50_000_000;
reg [32-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
always @ (CNTVAL) begin
if(CNTVAL == MAX_VAL)
OV = 1'b1;
else
OV = 1'b0;
end
endmodule
//
module cnt_en_clear_stop_0to9(
CLK , // clock
CNTVAL, // counter value
EN ,
CLEAR ,
STOP,
OV ); // overflow
input CLK;
input EN,CLEAR,STOP;
output [4-1:0] CNTVAL;
output OV;
reg [4-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(CLEAR) CNTVAL <= 4'b0000;
else begin
if(!STOP) begin
if(EN) begin // work enable
if(CNTVAL >= 9)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
else
CNTVAL <= CNTVAL ; // hold same value
end
end
end
always @ (CNTVAL) begin
if(CNTVAL == 9)
OV = 1'b1;
else
OV = 1'b0;
end
endmodule
//
module dec_4to9(
input [3:0]IN , // input
output reg [7:0] OUT ); // output
// get the OUT
always @ (IN) begin
case(IN)
4'b0000: OUT = 8'b1100_0000; //0
4'b0001: OUT = 8'b1111_1001;//1
4'b0010: OUT = 8'b1010_0100;//2
4'b0011: OUT = 8'b11011_0000;//3
4'b0100: OUT = 8'b1001_1001;//4
4'b0101: OUT = 8'b1001_0010;//5
4'b0110: OUT = 8'b1000_0010;//6
4'b0111: OUT = 8'b1111_1000;//7
4'b1000: OUT = 8'b1000_0000;//8
4'b1001: OUT = 8'b1001_0000;//9
// full case 不需要写default,否则一定要有default
endcase
end
endmodule
实验五 多周期移位寄存器
学生实验
• 编译下载电路观察现象
• 拨动SW0开关,观察LED的闪烁变换情况
• 设计新的功能 – 在原有的电路基础上,添加方向选择功能。
– SW0仍然是移位寄存器组的输入
– 使用SW1开关,控制移位寄存的方向
– 从实验现象上应当能够看到,SW1可以控制LED闪烁的 移动方向,以及控制SW0值的对LED组的输入位置(即 从LED组的最左边或是最右边)
串入并出移位寄存器 /
module shift_reg_SIPO(
RST , // 异步复位, 高有效
CLK , // 时钟,上升沿有效
EN , // 输入数据串行移位使能
IN , // 输入串行数据
SW1 ,
OUT ); // 并行输出数据
parameter SHLEN = 6;
input RST, CLK, EN,SW1;
input IN;
output[SHLEN-1:0] OUT;
reg [SHLEN-1:0] shift_R;
assign OUT[SHLEN-1:0] = shift_R[SHLEN-1:0];
// 时序逻辑 根据输入使能进行串行移位
// shift_R 会被编译为D触发器
always @ (posedge CLK or posedge RST) begin
if(RST)
shift_R[SHLEN-1:0] <= 0;
else
if(EN&&SW1==1) begin // 串行移位的使能有效
shift_R[SHLEN-1:1] <= shift_R[SHLEN-2:0];
shift_R[0] <= IN;
end
else if(EN&&!SW1) begin
shift_R[4:0]=shift_R[5:1];
shift_R[5]=IN;
end
else begin // 使能无效保持不动
shift_R[SHLEN-1:0] <= shift_R[SHLEN-1:0];
end
end // always
endmodule
时间基准计数器 /
module cnt_sync(
CLK , // clock
CNTVAL, // counter value
OV ); // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 25_000_000;
reg [32-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
always @ (CNTVAL) begin
if(CNTVAL == MAX_VAL)
OV = 1'b1;
else
OV = 1'b0;
end
endmodule // module cnt_en_0to9
实验六 计数器、ROM和DDS
学生实验 1
电路的工作时钟是fsys = 50MHz, 拨动开关,观察不同频率的正弦波
SW1
sw2
sw3
sw6
– 参考设计中,计数器和ROM 地址 都是 7 比特,连接关系如下图所示
– 根据理论分析和实验结果,回答以下问题
– 请回答,你能得到的正弦波频率和计数器增量值的对应关系是什么?
由波形可以看出计数增量越大,产生的正弦波波形的频率就越高。
• 设输出正弦波频率为f1,电路系统时钟为 fsys, 计数器步进增量为 CNT
• 请给出 f1 和 fsys 以及 CNT 关系的数学表达式
表达式的关系为f1=fsys*CNT/128
– 请回答,你能得到的最低频率的正弦波是多少?
当增量为1时,正弦波的频率为50Mhz/128
学生实验2
• 时钟频率保持fsys = 50MHz 不变,
• 修改电路,把计数器的计数值和输入的计数增量信号都改为9比特, 计数值的高7位连接ROM的地址线,低2位悬空。如下图所示。
– 把9比特的计数器增量输入信号连接到9个拨码开关上
to, location
CLK50,PIN_G21
SW[8],PIN_E4
SW[7],PIN_E3
SW[6],PIN_H7
SW[5],PIN_J7
SW[4],PIN_G5
SW[3] , PIN_G4
SW[2], PIN_H6
SW[1] , PIN_J6
SW[0], PIN_H5
– 根据理论分析和实验结果,回答以下问题
– 请回答,你能得到的正弦波频率和计数器增量值的对应关系是什么?
• 设输出正弦波频率为f1,电路系统时钟为 fsys, 计数器步进增量为 CNT
• 请给出 f1 和 fsys 以及 CNT 关系的数学表达式
表达式的关系为f1=fsys*CNT/512
– 请回答,在这种连接方式下,你能得到的最低频率的正弦波是多少
当增量为1时,正弦波的频率为50Mhz/512