按照篮球赛赛制进行设计。须具有24秒倒计时功能,十二分钟计时功能,暂停功能,进球计分功能(1分,2分,3分)等。
这个篮球计分器的实现采用top-down思想,具体分为6个模块 分别为 控制模块、计分模块、计时模块、24s倒计时模块、按键消抖模块、数码管显示模块。
这个篮球计分器的输入根据功能分析有以下几个:系统时钟、复位信号、暂停信号、加分信号(one、two、three)、控制给哪个队伍加分的信号;输出信号由于只有在数码管上显示,所以输出信号就只有数码管的段选与位选。
(1)、top模块
top模块主要是要了解各个模块之间的连接方式,具体如下图所示:

根据上图所示,top模块代码应该为:
module top(
input clk, //系统时钟
input rst, //复位信号
input stop, //计时暂停 (拨码按键)
input team, //选择加分的队伍 (拨码按键)
input ctrl, //切换挡位 (按键)
input one, //加一分 (按键)
input two, //加两分 (按键)
input three, //加三分 (按键)
output wire [3:0] sel, //数码管位选
output wire [6:0] seg //数码管段选
);
wire key_one;
wire key_two;
wire key_three;
wire [15:0] date1;
wire [15:0] date2;
wire [15:0] date3;
wire en;
wire key_ctrl;
wire [2:0] out_ctrl;
//计分模块
xiaodou s0 (
.clk(clk),
.rst(rst),
.key_in(one),
.key_flag(key_one)
);
xiaodou s1 (
.clk(clk),
.rst(rst),
.key_in(two),
.key_flag(key_two)
);
xiaodou s2 (
.clk(clk),
.rst(rst),
.key_in(three),
.key_flag(key_three)
);
jifen s3 (
.clk(clk),
.rst(rst),
.key_one(key_one),
.key_two(key_two),
.key_three(key_three),
.team(team),
.date2(date2)
);
//计时模块
jishi a0 (
.clk(clk),
.rst(rst),
.stop(stop),
.date1(date1)
);
//倒计时模块
daojishi b0 (
.clk(clk),
.rst(rst),
.en(en),
.date3(date3)
);
//控制模块
xiaodou c0 (
.clk(clk),
.rst(rst),
.key_in(ctrl),
.key_flag(key_ctrl)
);
ctrl c1(
.clk(clk),
.rst(rst),
.key_ctrl(key_ctrl),
.en(en),
.ctrl(out_ctrl)
);
//显示模块
xianshi d0 (
.clk(clk),
.rst(rst),
.ctrl(out_ctrl),
.date1(date1),
.date2(date2),
.date3(date3),
.sel(sel),
.seg(seg)
);
endmodule
(2)、控制模块
控制模块主要功能是切换挡位,本模块他的输入是有:系统时钟、复位信号和经过按键消抖后的一个脉冲信号;其输出是一个控制数码管显示的一个信号和倒计时模块的使能信号en,由于我们要控制倒计时模块何时开始倒计时,所以要引入这个使能信号,也就是按下ctrl按钮切换到倒计时模块时就开始倒计时。
具体代码如下:
module ctrl(
input clk,
input rst,
input key_ctrl,
output reg en,
output reg [2:0] ctrl
);
reg [1:0] cnt;
always@(posedge clk or negedge rst) begin
if(rst==0)
cnt<=0;
else if(cnt=='d2&&key_ctrl == 1)
cnt<=0;
else if(key_ctrl == 1)
cnt<=cnt+1'd1;
end
always@(posedge clk or negedge rst) begin
if(rst==0) begin
ctrl<=0;
en<=0;
end
else if(cnt==0) begin
ctrl<=3'b000;
en <=0;
end
else if(cnt==1) begin
ctrl<=3'b001;
en<=0;
end
else if(cnt=='d2) begin
ctrl<=3'b010;
en<=1;
end
end
endmodule
(3)、计时模块
计时模块的主要功能是12分钟的计时并将现在所及的时间转化为16位的输出信号(输出信号为BCD码前八位表示分钟,后八位表示秒数), 计时模块的输入主要有:系统时钟、复位信号和一个暂停信号(stop)输出只有一个位宽为16位的数据信号;此模块中的暂停信号(stop)我们可以在一秒钟的计数器中加一个信号当stop拉高时停止记数,这样就可以将其暂停;
在此模块要注意如何将目前所及的时间转化为BCD码,在这里我使用的是BCD计数器,将分钟和秒数分开,分别用两个8位的数据来记录它们的数据,最后将其合并;
具体代码如下:
module jishi(
input clk,
input rst,
input stop,
output [15:0] date1
);
localparam TIME_1S='d49_999_999;
/* localparam TIME_1S='d4; */
reg [25:0] cnt_1s;
reg [7:0] dout_1;
reg [7:0] dout_2;
//一秒钟的计数器
always@(posedge clk or negedge rst) begin
if(rst==0)
cnt_1s<='d0;
else if(cnt_1s == TIME_1S)
cnt_1s<='d0;
else if(stop==0)
cnt_1s<= cnt_1s + 1'd1;
else
cnt_1s<=cnt_1s;
end
//当前的秒数 并转化为bcd码
always@(posedge clk or negedge rst)begin
if(rst==0)
dout_2<=1'd0;
else if(dout_2[7:4]==4'b0101&&dout_2[3:0]==4'b1001&&cnt_1s == TIME_1S)
dout_2<=1'd0;
else if(dout_2[3:0]==4'b1001&&cnt_1s == TIME_1S) begin
dout_2[3:0]<=0;
dout_2[7:4]<=dout_2[7:4]+1'd1;
end
else if(cnt_1s == TIME_1S)
dout_2[3:0]<=dout_2[3:0]+1'b1;
end
//当前的分钟数并转化为bcd码
always@(posedge clk or negedge rst)begin
if(rst==0)
dout_1<=1'd0;
else if(dout_1[7:4]==4'b0001&&dout_1[3:0]==4'b0010&&cnt_1s == TIME_1S)
dout_1<=1'd0;
else if(dout_1[3:0]==4'b1001&&cnt_1s == TIME_1S) begin
dout_1[3:0]<=0;
dout_1[7:4]<=dout_1[7:4]+1'd1;
end
else if(dout_2[7:4]==4'b0101&&dout_2[3:0]==4'b1001&&cnt_1s == TIME_1S)
dout_1[3:0]<=dout_1[3:0]+1'b1;
end
assign date1={dout_1[7:0],dout_2[7:0]};
endmodule
(4)、计分模块
计分模块的主要功能是计算并记录目前两队的分数并将其转化为16位的输出信号;本模块的输入有:系统时钟、复位信号和三个经过消抖后的计分信号(key_one、key_two、key_three)输出只有一个位宽为16位的数据信号;
这里将数据转化为BCD码是要注意:由于我们不知道所加的分数是多少,所以有可能在加分后个位的分数大于9,所以此时BCD计数器在进位时要这要改写:
else if(dout_1[3:0] >= 4'b1001) begin
dout_1[3:0] <= dout_1[3:0]-'d9;
dout_1[7:4] <= dout_1[7:4] + 1'b1;
end
此模块代码如下:
module jifen(
input clk, //系统时钟
input rst, //复位信号
input key_one, //加一分
input key_two, //加两分
input key_three, //加三分
input team, //控制给那个队伍加分
output wire [15:0] date2 //输出的数据
);
/* reg [6:0] score1; //目前该加几分
reg [6:0] score2; //目前该加几分 */
reg [7:0] dout_1;
reg [7:0] dout_2;
//计算加分并将其转化为bcd码
//第一队
always@(posedge clk or negedge rst) begin
if(rst==0)
dout_1 <= 8'b00000000;
else if(dout_1[3:0] >= 4'b1001) begin
dout_1[3:0] <= dout_1[3:0]-'d9;
dout_1[7:4] <= dout_1[7:4] + 1'b1;
end
else if(key_one == 1'b1 && team == 0) begin
dout_1[7:4] <= dout_1[7:4];
dout_1[3:0] <= dout_1[3:0] + 1'b1;
end
else if(key_two == 1'b1 && team == 0) begin
dout_1[7:4] <= dout_1[7:4];
dout_1[3:0] <= dout_1[3:0] + 'd2;
end
else if(key_three == 1'b1 && team == 0) begin
dout_1[7:4] <= dout_1[7:4];
dout_1[3:0] <= dout_1[3:0] + 'd3;
end
end
//第二队
always@(posedge clk or negedge rst) begin
if(rst==0)
dout_2 <= 8'b00000000;
else if(dout_2[3:0] >= 4'b1001)
begin
dout_2[3:0] <= dout_2[3:0]-'d9;
dout_2[7:4] <= dout_2[7:4] + 1'b1;
end
else if(key_one == 1'b1 && team == 1) begin
dout_2[7:4] <= dout_2[7:4];
dout_2[3:0] <= dout_2[3:0] + 1'b1;
end
else if(key_two == 1'b1 && team == 1) begin
dout_2[7:4] <= dout_2[7:4];
dout_2[3:0] <= dout_2[3:0] + 'd2;
end
else if(key_three == 1'b1 && team == 1) begin
dout_2[7:4] <= dout_2[7:4];
dout_2[3:0] <= dout_2[3:0] + 'd3;
end
end
//将bcd码转为将要赋值的数据
assign date2={dout_1[7:0],dout_2[7:0]};
endmodule
(5)、倒计时模块
倒计时模块的主要功能是24s的倒计时并将目前的时间转化为BCD码;本模块的输入是系统时钟、复位信号和一个有控制模块输出的使能信号(用来控制何时开始倒计时);输出是一个16位的数据信号(BCD码)用来表示目前的时间;
本模块中同样采用BCD计数器将数据信号转化为BCD码,不过与之前不同的是采用减法记数;
本模块代码如下:
module daojishi(
input clk,//系统时钟
input rst,//复位信号
input en,//判断何时开始倒计时 由控制模块输入
output [15:0] date3 //输出的数据信号
);
localparam TIME_001S='d499999;
/* localparam TIME_001S='d4; */
reg [7:0] dout_1;
reg [7:0] dout_2;
reg [18:0] cnt_001s;
always@(posedge clk or negedge rst) begin
if(rst==0)
cnt_001s<=0;
else if(en==0)
cnt_001s<=0;
else if(cnt_001s == TIME_001S)
cnt_001s<=0;
else
cnt_001s<=cnt_001s +1;
end
always@(posedge clk or negedge rst) begin
if(rst==0)
dout_2<=8'b0000_0000;
else if(en==0)
dout_2<=8'b0000_0000;
else if(dout_1==0&&dout_2==0&&cnt_001s == TIME_001S)
dout_2<=dout_2;
else if(dout_2==0&&cnt_001s == TIME_001S)
dout_2<=8'b1001_1001;
else if(dout_2[3:0]==0&&cnt_001s == TIME_001S) begin
dout_2[7:4]<=dout_2[7:4] - 1'b1;
dout_2[3:0]<=4'b1001;
end
else if(cnt_001s == TIME_001S)
dout_2[3:0]<=dout_2[3:0] - 1'b1;
end
always@(posedge clk or negedge rst) begin
if(rst==0)
dout_1<=8'b0010_0100;
else if(en==0)
dout_1<=8'b0010_0100;
else if(dout_1==0&&cnt_001s == TIME_001S)
dout_1<=dout_1;
else if(dout_1[3:0]==0&&cnt_001s == TIME_001S) begin
dout_1[7:4]<=dout_1[7:4] - 1'b1;
dout_1[3:0]<=4'b1001;
end
else if(dout_2==0&&cnt_001s == TIME_001S)
dout_1[3:0]<=dout_1[3:0] - 1'b1;
end
assign date3={dout_1[7:0],dout_2[7:0]};
endmodule
(6)、按键消抖模块
按键消抖模块的主要功能是将一个输入的按键信号滤波转化为一个脉冲信号;具体实现办法可以参见小梅哥《零基础轻松学习FPGA,小梅哥FPGA设计思想与验证方法视频教程》
具体代码如下:
module xiaodou(
input clk,
input rst,
input key_in,
output reg key_flag //滤波后的信号(脉冲信号)
);
localparam
IDEL = 4'b0001,
FILTER0 = 4'b0010,
DOWN = 4'b0100,
FILTER1 = 4'b1000;
reg [3:0] state;
reg key_tem0;
reg key_tem1;
wire nedge;
wire pedge;
reg [19:0] cnt; //二十毫秒计数器
reg en_cnt; //计数器使能信号
reg cnt_full;//计数器记满信号
//边沿检测
always@(posedge clk or negedge rst) begin
if(rst==0) begin
key_tem0<=0;
key_tem1<=0;
end
else begin
key_tem0 <= key_in;
key_tem1 <= key_tem0;
end
end
assign nedge = !key_tem0 & key_tem1; //下降沿
assign pedge = key_tem0 & (!key_tem1); //上升沿
//一段式状态机
always@(posedge clk or negedge rst )begin
if(rst==0) begin
state <= IDEL;
en_cnt <= 1'b0;
key_flag<=1'd0;
end
else
case(state)
IDEL:
begin
key_flag<=1'b0;
if(nedge) begin
state <= FILTER0;
en_cnt <= 1'b1; //计数器记数
end
else
state <= IDEL;
end
FILTER0:
if(cnt_full) begin
state<= DOWN;
en_cnt<=1'b0;
key_flag<=1'b1;
end
else if(pedge) begin
state<= IDEL;
en_cnt <= 1'b0;
end
else
state<= FILTER0;
DOWN:
begin
key_flag<=1'b0;
if(pedge) begin
state<=FILTER1;
en_cnt<=1'b1;
end
else
state<= DOWN;
end
FILTER1:
if(cnt_full) begin
state<= IDEL;
en_cnt<=1'b0;
key_flag<=1'b0;
end
else if(nedge) begin
state<= DOWN;
en_cnt <= 1'b0;
end
else
state<= FILTER1;
default: begin
state<=IDEL;
en_cnt<=1'b0;
key_flag<=1'b0;
end
endcase
end
//二十毫秒计数器
always@(posedge clk or negedge rst) begin
if(rst==0)
cnt <= 20'd0;
else if(en_cnt)
cnt <= cnt + 1'b1;
else
cnt<= 20'd0;
end
always@(posedge clk or negedge rst) begin
if(rst==0)
cnt_full <= 1'b0;
else if(cnt == 'd999_999)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
end
endmodule
(7)、数码管显示模块
数码管显示模块的主要功能是将输入其中的16位数据信号通过动态扫描的方式输出在数码管上,本模块的输入有系统时钟、复位信号、由控制模块输入的控制信号和由计时、计分、倒计时三个模块输出的数据信号,输出也就是整个计分器的输出:4位的数码管位选sel和7位的数码管段选seg;
本模块通过译码器的方式来实现数据选择:
always@(posedge clk or negedge rst) begin
if(rst==0)
disp_data<=0;
else
case(ctrl)
3'b000:disp_data<=date1;
3'b001:disp_data<=date2;
3'b010:disp_data<=date3;
default:disp_data<=0;
endcase
end
本模块的代码如下:
module xianshi(
input clk,
input rst,
input [2:0] ctrl,
input [15:0] date1,//数据信号
input [15:0] date2,//数据信号
input [15:0] date3,//数据信号
output reg [3:0] sel, // 数码管位选(选择当前要显示的数码管)
output reg [6:0] seg // 数码管段选(选择当前要显示的内容)
);
reg [14:0] cnt_1; //分频记数的计数器
reg clk_out; //分频后的时钟信号
/* reg [3:0] sel_r; //表示那个数码管亮 */
reg [3:0] date_tmp;
reg [15:0] disp_data;
localparam TIME='d24999;
/* localparam TIME='d4; */
always@(posedge clk or negedge rst) begin
if(rst==0)
disp_data<=0;
else
case(ctrl)
3'b000:disp_data<=date1;
3'b001:disp_data<=date2;
3'b010:disp_data<=date3;
default:disp_data<=0;
endcase
end
//cnt_1的记数模块
always@(posedge clk or negedge rst) begin
if(rst==0)
cnt_1 <= 15'd0;
else if(cnt_1 ==TIME)
cnt_1 <= 15'd0;
else
cnt_1 <= cnt_1+1'd1;
end
//时钟分频模块
always@(posedge clk or negedge rst) begin
if(rst==0)
clk_out<=1'b0;
else if(cnt_1== TIME)
clk_out<=~clk_out;
else
clk_out<=clk_out;
end
//移位寄存器
always@(posedge clk_out or negedge rst) begin
if(rst==0)
sel<=4'b0001;
else if(sel==4'b1000)
sel<=4'b0001;
else
sel<=sel<<1;
/* if(rst==0)
sel_r<=4'b0001;
else
sel_r<={sel_r[2:0],sel_r[3]}; */
end
//四选一多路器
always@(*) begin
case(sel)
4'b0001 : date_tmp <= disp_data[3:0];
4'b0010 : date_tmp <= disp_data[7:4];
4'b0100 : date_tmp <= disp_data[11:8];
4'b1000 : date_tmp <= disp_data[15:12];
default:date_tmp<=4'b0000;
endcase
end
//字典(译码器)
always@(*) begin
case(date_tmp)
4'h0:seg<=7'b1000000;
4'h1:seg<=7'b1111001;
4'h2:seg<=7'b0100100;
4'h3:seg<=7'b0110000;
4'h4:seg<=7'b0011001;
4'h5:seg<=7'b0010010;
4'h6:seg<=7'b0000010;
4'h7:seg<=7'b1111000;
4'h8:seg<=7'b0000000;
4'h9:seg<=7'b0010000;
4'ha:seg<=7'b0001000;
4'hb:seg<=7'b0000011;
4'hc:seg<=7'b1000110;
4'hd:seg<=7'b0100001;
4'he:seg<=7'b0000110;
4'hf:seg<=7'b0001110;
endcase
end
//
endmodule
本人是刚入门FPGA的一名在读大学生,由于初学代码也表现出冗长,凌乱等诸多问题,望见谅。
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源
我正在根据Rakefile中的现有测试文件动态生成测试任务。假设您有各种以模式命名的单元测试文件test_.rb.所以我正在做的是创建一个以“测试”命名空间内的文件名命名的任务。使用下面的代码,我可以用raketest:调用所有测试require'rake/testtask'task:default=>'test:all'namespace:testdodesc"Runalltests"Rake::TestTask.new(:all)do|t|t.test_files=FileList['test_*.rb']endFileList['test_*.rb'].eachdo|task|n
我想要像“嘿那里”这样的东西变成,例如,#316583。我希望将任意长度的字符串“归结”为十六进制颜色。我不知道从哪里开始。我在想,每个字符串的MD5散列都是不同的-但如何将该散列转换为十六进制颜色数字? 最佳答案 你可以只取几位前几位:require'digest/md5'color=Digest::MD5.hexdigest('Mytext')[0..5] 关于ruby-如何使用Ruby基于字母数字字符串生成颜色?,我们在StackOverflow上找到一个类似的问题:
文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3
我正在尝试整个BDD方法并想测试AMQP基于Vanilla的方面Ruby我正在写的应用程序。选择Minitest后作为与其他名副其实的蔬菜框架不同的平衡功能和表现力的测试框架,我着手编写此规范:#File./test/specs/services/my_service_spec.rb#Requirementsfortestrunningandconfigurationrequire"minitest/autorun"require"./test/specs/spec_helper"#Externalrequires#MinitestSpecsforEventMachinerequire
我分1,000个批处理从服务器获取大约20,000个数据集。每个数据集都是一个JSON对象。坚持这会产生大约350MB的未压缩明文。我的内存限制为1GB。因此,我以追加模式将每1,000个JSON对象作为一个数组写入到一个原始JSON文件中。结果是一个包含20个需要聚合的JSON数组的文件。无论如何我都需要触摸它们,因为我想添加元数据。一般RubyYajlParser使这成为可能:raw_file=File.new(path_to_raw_file,'r')json_file=File.new(path_to_json_file,'w')datasets=[]parser=Yajl::
有什么方法可以查看gem是否仅在UNIX/类UNIX系统上受支持?是否有任何gem可以“筛选”所有gem并查看在Windows上使用它是否有任何问题。 最佳答案 简短回答:否。老实说,Windows在Ruby世界里是二等公民。这主要是因为Linux、BSD、OSX和几乎所有其他基于POSIX的系统都同意一件事,而Windows将去做完全不同的事情。即使是用于Windows的gem也可能偶尔会由于开发人员的疏忽而损坏。大多数gem作者没有针对Windows运行并依赖于用户错误报告的持续集成服务器。支持Windows很困难,不仅因为AP