设计任务
1、四人通过按键抢答,最先按下按键的人抢答成功,此后其他人抢答无效,抢答成功的人对应的LED灯亮。
2、每次只有一人可获得抢答资格,一次抢答完后主持人通过复位按键复位,选手再从新抢答。
3、有重新开始游戏按键,游戏从新开始时每位选手有5分的初始分,答对加1分,答错扣1分,最高分不能超过9分,最低为0分。
4、每位选手和主持人共有30秒时间进行回答和加减分,在此期间,RGB为蓝色灯;超过30秒,RGB变为红色,即报警;未开始抢答,则RGB灯为绿色。
5、选手抢答成功时通过数码管显示其对应的分数。
代码分析
- 本次设计共有7个模块:
模块 | 功能 |
---|---|
common.v | 头文件 |
devide.v | 用来对时钟进行分频 |
counter.v | 计时30秒 |
debounce.v | 按键消抖 |
segment.v | 数码管显示 |
snatch.v | 抢答,定义了抢答规则,并开始计时30s |
score.v | 分数,用来对选手加分减分等 |
qiangdaqi.v | 顶层文件 |
- 设计代码
- common.v
//*************************************************************
//
//*@File name: common.v
//
//*@File type: verilog
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-07 11:26:28
//
//*@Function : Some Macros.
//
//*************************************************************
/* Used in unblocking */
/* Just to be convenient to watch the waves in RTL level */
`define DEL 1
/* Define your own macro here */
`define SIM 1
- devide.v
// ********************************************************************
// File name : divide.v
// Module name : divide
// Author :
// Description : clock divider
// Module Function:任意整数时钟分频
// ********************************************************************
module divide ( clk,rst_n,clkout);
input clk,rst_n; //输入信号,其中clk连接到FPGA的C1脚,频率为12MHz
output clkout; //输出信号,可以连接到LED观察分频的时钟
parameter WIDTH = 24; //计数器的位数,计数的最大值为 2**WIDTH-1
parameter N = 12000000; //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出
reg [WIDTH-1:0] cnt_p,cnt_n; //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器
reg clk_p,clk_n; //clk_p为上升沿触发时分频时钟,clk_n为下降沿触发时分频时钟
//上升沿触发时计数器的控制
always @ (posedge clk or negedge rst_n ) //posedge和negedge是verilog表示信号上升沿和下降沿
//当clk上升沿来临或者rst_n变低的时候执行一次always里的语句
begin
if(!rst_n)
cnt_p<=0;
else if (cnt_p==(N-1))
cnt_p<=0;
else cnt_p<=cnt_p+1; //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器
end
//上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_p<=0;
else if (cnt_p<(N>>1)) //N>>1表示右移一位,相当于除以2去掉余数
clk_p<=0;
else
clk_p<=1; //得到的分频时钟正周期比负周期多一个clk时钟
end
//下降沿触发时计数器的控制
always @ (negedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_n<=0;
else if (cnt_n==(N-1))
cnt_n<=0;
else cnt_n<=cnt_n+1;
end
//下降沿触发的分频时钟输出,和clk_p相差半个时钟
always @ (negedge clk)
begin
if(!rst_n)
clk_n<=0;
else if (cnt_n<(N>>1))
clk_n<=0;
else
clk_n<=1; //得到的分频时钟正周期比负周期多一个clk时钟
end
assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;//条件判断表达式
//当N=1时,直接输出clk
//当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p
//当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&clk_n。正周期多所以是相与
endmodule
- counter.v
//*************************************************************
//
//*@File name: counter.v
//
//*@File type: verilog
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-07 11:22:56
//
//*@Function : Count 30s
//
//*************************************************************
//
// Head files
`include "common.v"
//
// Module definition
module counter(
clk ,
rst_n ,
start ,
valid
);
input clk ;
input rst_n ;
input start ;
output valid ;
reg valid ;
//
// Generate the 1Hz clock
wire clkout_1hz;
`ifdef SIM
// 12Mhz in simulation mode, just to reduce sim time
divide #(.N(1)) devide_u1 (
.clk ( clk ) ,
.rst_n ( rst_n ) ,
.clkout( clkout_1hz )
);
`else
// 1Hz in real mode
divide devide_u1(
.clk ( clk ) ,
.rst_n ( rst_n ) ,
.clkout( clkout_1hz )
);
`endif
/
//*Function Description:
//* Detect the rise edge of clkout_1hz as enable signal
//*
/
//
reg clkout_1hz_q;
wire clkout_1hz_flag;
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
clkout_1hz_q <= #`DEL 1'b0;
end
else begin
clkout_1hz_q <= #`DEL clkout_1hz;
end
end
assign clkout_1hz_flag = ( ~clkout_1hz_q ) && ( clkout_1hz );
//
// Delay of start
reg start_dly;
reg [4:0] cnt_1s;
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
start_dly <= #`DEL 1'b0;
end
else if( start ) begin
start_dly <= #`DEL 1'b1;
end
else if( cnt_1s == 5'd29 ) begin
start_dly <= #`DEL 1'b0;
end
end
//
// Count by 1s
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
cnt_1s <= #`DEL 5'd0;
end
else if( start_dly ) begin
if( clkout_1hz_flag ) begin
cnt_1s <= #`DEL cnt_1s + 1'b1;
end
end
else begin
cnt_1s <= #`DEL 5'd0;
end
end
//
// Generate the end signal: valid
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
valid <= #`DEL 1'b0;
end
else if( cnt_1s == 5'd29 ) begin
valid <= #`DEL 1'b1;
end
else begin
valid <= #`DEL 1'b0;
end
end
endmodule
- debounce.v
// ********************************************************************
// File name : debounce.v
// Module name : debounce
// Description :
// Module Function:按键消抖
// ********************************************************************
`include "common.v"
module debounce (clk,rst,key,key_pulse);
parameter N = 1; //要消除抖动的按键的数量
input clk;
input rst;
input [N-1:0] key; //输入的按键
output [N-1:0] key_pulse; //按键动作产生的脉冲一个时钟周期高电平
reg [N-1:0] key_rst_pre; //定义一个寄存器型变量存储上一个触发时的按键值
reg [N-1:0] key_rst; //定义一个寄存器变量储存储当前时刻触发的按键值
wire [N-1:0] key_edge; //检测到按键由高到低变化时产生一个高脉冲
//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
always @(posedge clk or negedge rst)
begin
if (!rst) begin
key_rst <= {N{1'b1}}; //初始化时给key_rst赋值全为1,{}中表示N个1
key_rst_pre <= {N{1'b1}};
end
else begin
key_rst <= key; //第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre
key_rst_pre <= key_rst; //非阻塞赋值。相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值
end
end
//脉冲边沿检测。当key检测到下降沿时,key_edge产生一个时钟周期的高电平
assign key_edge = key_rst_pre & (~key_rst);
reg [17:0] cnt; //产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器
//产生20ms延时,当检测到key_edge有效是计数器清零开始计数
always @(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 18'h0;
else if(key_edge)
cnt <= 18'h0;
else
cnt <= cnt + 1'h1;
end
reg [N-1:0] key_sec_pre; //延时后检测电平寄存器变量
reg [N-1:0] key_sec;
//延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec <= {N{1'b1}};
else if (cnt==18'h3ffff)
key_sec <= key;
end
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec_pre <= {N{1'b1}};
else
key_sec_pre <= key_sec;
end
assign key_pulse = key_sec_pre & (~key_sec);
endmodule
- segment.v
// ********************************************************************
// File name : segment.v
// Module name : segment
// Description : segment initial
// Module Function:数码管的译码模块初始化
// ********************************************************************
module segment (seg_data_1,seg_data_2,seg_led_1,seg_led_2);
input [3:0] seg_data_1; //数码管需要显示0~9十个数字,所以最少需要4位输入做译码
input [3:0] seg_data_2; //小脚丫上第二个数码管
output [8:0] seg_led_1; //在小脚丫上控制一个数码管需要9个信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A
output [8:0] seg_led_2; //在小脚丫上第二个数码管的控制信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A
reg [8:0] seg [9:0]; //定义了一个reg型的数组变量,相当于一个10*9的存储器,
initial begin
seg[0] = 9'h3f; //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0
seg[1] = 9'h06; //7段显示数字 1
seg[2] = 9'h5b; //7段显示数字 2
seg[3] = 9'h4f; //7段显示数字 3
seg[4] = 9'h66; //7段显示数字 4
seg[5] = 9'h6d; //7段显示数字 5
seg[6] = 9'h7d; //7段显示数字 6
seg[7] = 9'h07; //7段显示数字 7
seg[8] = 9'h7f; //7段显示数字 8
seg[9] = 9'h6f; //7段显示数字 9
end
assign seg_led_1 = seg[seg_data_1]; //连续赋值,这样输入不同四位数,
assign seg_led_2 = seg[seg_data_2]; //就能输出对于译码的9位输出
endmodule
- snatch.v
//*************************************************************
//
//*@File name: snatch.v
//
//*@File type: verilog
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-07 21:00:41
//
//*@Function : Detect the key pressed
//
//*************************************************************
//
// Head files
`include "common.v"
//
// Module definition
//
module snatch(
clk ,
rst_n ,
key ,
reload , // Connect to the 3rd switch
led ,
valid_dly,
debug_key_pulse_reg,
debug_valid_dly,
debug_lock,
rgb
);
//
// Input and output signals
input clk ;
input rst_n ;
input [3:0] key ;
input reload ;
output [3:0] led ;
output [2:0] rgb ;
output valid_dly ;
reg [3:0] led ;
reg [2:0] rgb ;
reg valid_dly;
//
// Debug signal
output [3:0] debug_key_pulse_reg ;
output debug_valid_dly ;
output debug_lock ;
//
// Key debounce instantiation
wire [3:0] key_pulse;
debounce #(.N(4)) debounce_u1(
.clk ( clk ) ,
.rst ( rst_n ) ,
.key ( key ) ,
.key_pulse( key_pulse )
);
//
// Used to store the key_pulse for long
reg [3:0] key_pulse_reg;
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
key_pulse_reg <= #`DEL 4'b0000;
end
else if( |key_pulse & ~lock ) begin
key_pulse_reg <= #`DEL key_pulse;
end
else if( reload ) begin
key_pulse_reg <= #`DEL 4'd0;
end
end
assign debug_key_pulse_reg = key_pulse_reg;
//
// Judge player
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
led <= #`DEL 4'b1111;
end
else if( key_pulse_reg[3] ) begin
led <= #`DEL 4'b0111;
end
else if( key_pulse_reg[2] ) begin
led <= #`DEL 4'b1011;
end
else if( key_pulse_reg[1] ) begin
led <= #`DEL 4'b1101;
end
else if( key_pulse_reg[0] ) begin
led <= #`DEL 4'b1110;
end
else begin
led <= #`DEL 4'b1111;
end
end
//
// Signal: lock
// The key was pressed, the lock is valid
// Then the value of key is invalid until the reload coming
reg lock;
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
lock <= #`DEL 1'b0;
end
else if( reload ) begin
lock <= #`DEL 1'b0;
end
else if( key_pulse_reg[3] || key_pulse_reg[2] || key_pulse_reg[1] || key_pulse_reg[0] ) begin
lock <= #`DEL 1'b1;
end
else begin
lock <= #`DEL lock;
end
end
assign debug_lock = ~lock;
//
// Detect the rise edge of lock
reg lock_q;
wire lock_flag;
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
lock_q <= #`DEL 1'b0;
end
else begin
lock_q <= #`DEL lock;
end
end
assign lock_flag = ( ~lock_q ) && ( lock );
//
// Counter instantiation
// When detect the rise edge of lock, then begin to count
counter counter_u1(
.clk ( clk ) ,
.rst_n ( rst_n ) ,
.start ( lock_flag ) ,
.valid ( valid )
);
//
// valid is a pulse signal, so there need a delay of valid
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
valid_dly <= #`DEL 1'b0;
end
else if( valid ) begin
valid_dly <= #`DEL 1'b1;
end
else if( reload ) begin
valid_dly <= #`DEL 1'b0;
end
end
assign debug_valid_dly = ~valid_dly;
//
// RGB display
// if lock == 0, green
// if lock == 1, blue
// if valid == 1, red
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
rgb <= #`DEL 3'b111;
end
else if( valid_dly ) begin
rgb <= #`DEL 3'b011;
end
else if( ~lock ) begin
rgb <= #`DEL 3'b101;
end
else if( lock ) begin
rgb <= #`DEL 3'b110;
end
end
endmodule
- score.v
//*************************************************************
//
//*@File name: score.v
//
//*@File type: verilog
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-08 08:41:02
//
//*@Function : Describe the score of players
//
//*************************************************************
//
// Head files
`include "common.v"
//
// Module definition
//
module score(
clk ,
rst_n ,
add_score ,
sub_score ,
led ,
lock ,
end_score
);
//===========================================================
//* Input and output signals
//===========================================================
input clk ;
input rst_n ;
input add_score ;
input sub_score ;
input lock ;
input [3:0] led ;
output [3:0] end_score ;
wire [3:0] end_score ;
//===========================================================
//* Internal signals
//===========================================================
reg [3:0] score_player[0:3];
//
// Switch debounce instantiation
wire [1:0] switch_pulse;
debounce #(.N(2)) debounce_u1(
.clk ( clk ) ,
.rst ( rst_n ) ,
.key ( {add_score,sub_score} ) ,
.key_pulse( switch_pulse )
);
wire add_score_flag, sub_score_flag;
assign {add_score_flag, sub_score_flag} = switch_pulse;
/
//*Function Description:
//* Display the initial score
//* Add or sub one score at the same time
/
//
always @( posedge clk or negedge rst_n ) begin
if( ~rst_n ) begin
score_player[0] <= #`DEL 4'd5;
score_player[1] <= #`DEL 4'd5;
score_player[2] <= #`DEL 4'd5;
score_player[3] <= #`DEL 4'd5;
end
else if( ~&led && ~lock ) begin
case(1'b1)
~led[0]:begin
if( add_score_flag ) begin
if( score_player[0] < 4'd9 ) begin
score_player[0] <= #`DEL score_player[0] + 1'b1;
end
end
else if( sub_score_flag ) begin
if( |score_player[0] ) begin
score_player[0] <= #`DEL score_player[0] - 1'b1;
end
end
end
~led[1]:begin
if( add_score_flag ) begin
if( score_player[1] < 4'd9 ) begin
score_player[1] <= #`DEL score_player[1] + 1'b1;
end
end
else if( sub_score_flag ) begin
if( |score_player[1] ) begin
score_player[1] <= #`DEL score_player[1] - 1'b1;
end
end
end
~led[2]:begin
if( add_score_flag ) begin
if( score_player[2] < 4'd9 ) begin
score_player[2] <= #`DEL score_player[2] + 1'b1;
end
end
else if( sub_score_flag ) begin
if( |score_player[2] ) begin
score_player[2] <= #`DEL score_player[2] - 1'b1;
end
end
end
~led[3]:begin
if( add_score_flag ) begin
if( score_player[3] < 4'd9 ) begin
score_player[3] <= #`DEL score_player[3] + 1'b1;
end
end
else if( sub_score_flag ) begin
if( |score_player[3] ) begin
score_player[3] <= #`DEL score_player[3] - 1'b1;
end
end
end
endcase
end
end
assign end_score = &led ? 4'd0 :
(~led[0] ? score_player[0] :
(~led[1] ? score_player[1] :
(~led[2] ? score_player[2] :
(~led[3] ? score_player[3] :
4'd0))));
endmodule
- qiangdaqi.v
//*************************************************************
//
//*@File name: qiangdaqi.v
//
//*@File type: verilog top module
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-08 11:11:08
//
//*@Function :
//
//*************************************************************
//
// Module definition
//
module qiangdaqi(
clk ,
rst_n ,
switch ,
key ,
led ,
rgb ,
seg_led_1
);
//===========================================================
//* Input and output signals
//===========================================================
//
input clk ;
input rst_n ;
input [2:0] switch ;
input [3:0] key ;
output [3:0] led ;
output [2:0] rgb ;
output [8:0] seg_led_1 ;
/
//*Function Description:
//* Module instantiation
//*
/
//
snatch snatch_u1(
.clk ( clk ),
.rst_n ( rst_n ),
.key ( key ),
.reload ( ~switch[2] ), // Connect to the 3rd switch
.led ( led ),
.valid_dly( valid_dly ) ,
.rgb ( rgb )
);
wire [3:0] end_score;
score score_u1(
.clk ( clk ),
.rst_n ( rst_n ),
.add_score ( switch[0] ),
.sub_score ( switch[1] ),
.lock ( valid_dly ),
.led ( led ),
.end_score ( end_score )
);
segment segment_u1(
.seg_data_1 ( end_score ) ,
.seg_data_2 ( ) ,
.seg_led_1 ( seg_led_1 ) ,
.seg_led_2 ( )
);
endmodule
- 仿真文件
- counter_tb.v
module counter_tb();
reg tb_clk ;
reg tb_rst_n;
reg tb_start;
wire tb_valid;
//
// Task of delay
task delay;
input [31:0] num;
begin
repeat(num) @(posedge tb_clk);
#1;
end
endtask
//
// Generate tb_clock
initial begin
tb_clk = 0;
end
always #10 tb_clk = ~tb_clk;
//
// Generate tb_reset
initial begin
tb_rst_n = 1;
delay(1);
tb_rst_n = 0;
delay(1);
tb_rst_n = 1;
end
//
// Dump file
initial begin
$dumpfile(" counter_tb.vcd ");
$dumpvars();
end
//
// Others signals
initial begin
tb_start = 1'b0;
// After reset
delay(3);
tb_start = 1'b1;
delay(1);
tb_start = 1'b0;
delay(40);
$finish;
end
//
// Instantiation
counter counter_u1(
.clk ( tb_clk ) ,
.rst_n ( tb_rst_n ) ,
.start ( tb_start ) ,
.valid ( tb_valid )
);
endmodule
- snatch_tb.v
//*************************************************************
//
//*@File name: snatch_tb.v
//
//*@File type: testbench
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-07 21:12:51
//
//*@Function :
//
//*************************************************************
//
// Head files
// `include "common.v"
//
// Module definition
//
module snatch_tb();
reg tb_clk ;
reg tb_rst_n ;
reg [3:0] tb_key ;
reg tb_reload ;
wire [3:0] tb_led ;
wire [2:0] tb_rgb ;
task delay;
input [31:0] num;
begin
repeat(num) @(posedge tb_clk);
#1;
end
endtask
initial begin
tb_clk = 0;
end
always #10 tb_clk = ~tb_clk;
initial begin
tb_rst_n = 1;
delay(1);
tb_rst_n = 0;
delay(1);
tb_rst_n = 1;
end
initial begin
$dumpfile(" snatch_tb.vcd ");
$dumpvars();
end
initial begin
tb_key = 4'b1111;
tb_reload = 1'b0;
delay(5); // rgb is green
tb_key = 4'b1100; // 3
delay(15); // rgb is bule
tb_reload = 1'b1;
delay(1);
tb_reload = 1'b0;
tb_key = 4'b0111; // 1
delay(40); // rgb is red, time out
tb_reload = 1'b1;
delay(1);
tb_reload = 1'b0;
tb_key = 4'b1010; // 1
delay(20); // rgb is blue
tb_reload = 1'b1;
delay(1);
tb_reload = 1'b0;
delay(5); // rgb is green
$finish;
end
snatch snatch_u1(
.clk ( tb_clk ) ,
.rst_n ( tb_rst_n ) ,
.key ( tb_key ) ,
.reload( tb_reload ) , // Connect to the 3rd switch
.led ( tb_led ) ,
.rgb ( tb_rgb )
);
endmodule
- score_tb.v
//*************************************************************
//
//*@File name: score_tb.v
//
//*@File type: testbench
//
//*@Version : 0.0.1
//
//*@Author : Zehua Dong, HITWH
//
//*@E-mail : hitdongzh@163.com
//
//*@Date : 2020-12-08 09:44:40
//
//*@Function :
//
//*************************************************************
//
// Head files
// `include "common.v"
//
// Module definition
//
module score_tb();
reg tb_clk ;
reg tb_rst_n ;
reg tb_add_score ;
reg tb_sub_score ;
reg [3:0] tb_led ;
wire [3:0] tb_end_score ;
task delay;
input [31:0] num;
begin
repeat(num) @(posedge tb_clk);
#1;
end
endtask
initial begin
tb_clk = 0;
end
always #10 tb_clk = ~tb_clk;
initial begin
tb_rst_n = 1;
delay(1);
tb_rst_n = 0;
delay(1);
tb_rst_n = 1;
end
initial begin
$dumpfile(" score_tb.vcd ");
$dumpvars();
end
initial begin
tb_add_score = 1'b0;
tb_sub_score = 1'b0;
tb_led = 4'b1111; // Display 0
delay(3);
tb_led = 4'b1011; // Display 5
delay(5);
tb_add_score = 1'b1; // Display 6
delay(2);
tb_add_score = 1'b0;
delay(5);
tb_led = 4'b0111; // Display 5
delay(5);
tb_sub_score = 1'b1; // Display 4
delay(2);
tb_sub_score = 1'b0;
delay(5);
$finish;
end
score score_u1(
.clk ( tb_clk ) ,
.rst_n ( tb_rst_n ) ,
.add_score( tb_add_score ) ,
.sub_score( tb_sub_score ) ,
.led ( tb_led ) ,
.end_score( tb_end_score )
);
endmodule
- qiangdaqi_tb.v
module qiangdaqi_tb();
reg tb_clk ;
reg tb_rst_n ;
reg [2:0] tb_switch ;
reg [3:0] tb_key ;
wire [3:0] tb_led ;
wire [2:0] tb_rgb ;
wire [8:0] tb_seg_led_1;
task delay;
input [31:0] num;
begin
repeat(num) @(posedge tb_clk);
#1;
end
endtask
initial begin
tb_clk = 0;
end
always #10 tb_clk = ~tb_clk;
initial begin
tb_rst_n = 1;
delay(1);
tb_rst_n = 0;
delay(1);
tb_rst_n = 1;
end
initial begin
$dumpfile(" qiangdaqi_tb.vcd ");
$dumpvars();
end
initial begin
tb_switch = 3'd0;
tb_key = 4'b1111; // green
delay(3);
tb_key = 4'b1001; // 2hao
delay(10); // blue
tb_switch = 3'b001;// 6 score
delay(1);
tb_switch = 3'b100;// reload
delay(1);
tb_switch = 3'b000;
delay(5);
tb_key = 4'b0111; // 1hao
delay(10); // blue
tb_switch = 3'b010; // 4 score
delay(1);
tb_switch = 3'b100;// reload
delay(1);
tb_switch = 3'b000;
delay(5);
tb_key = 4'b1110; // 4hao
delay(40); // red
tb_switch = 3'b100;// reload
delay(1);
tb_switch = 3'b000;
delay(10);
$finish;
end
qiangdaqi qiangdaqi_u1(
.clk ( tb_clk ),
.rst_n ( tb_rst_n ),
.switch ( tb_switch ),
.key ( tb_key ),
.led ( tb_led ),
.rgb ( tb_rgb ),
.seg_led_1 ( tb_seg_led_1 )
);
endmodule
- 仿真结果
- modelsim编译结果是没问题的,有几个warning无伤大雅,用来调试的
- 上板
工程是在QuartusII15.0中建立的
- RTL视图
-
顶层qiangdaqi视图
-
score视图
-
snatch视图
-
引脚分配
-
- 上板验证
- 上电后
- 正常抢答状态,rgb为蓝色,初始分数5分
- 超过30秒后,rgb变为红色,此时加分减分按键不起作用
- 上电后
- 减一分
- 加一分