基于Lattice MXO2的小脚丫FPGA核心板制作具有启动、停止、递增和清除功能的秒表
该项目使用了基于Lattice MXO2的小脚丫FPGA核心板,实现了秒表的设计,它的主要功能为:具有启动、停止、递增和清除功能。
标签
FPGA
参加活动/培训
Mengxun
更新2024-03-29
山东农业大学
187



项目需求

使用七段显示器作为输出设备,在小脚丫FPGA核心板上创建一个2位数秒表。

  1. 秒表应从 0.0 秒计数到 9.9秒,然后翻转,计数值每0.1秒精确更新一次。
  2. 秒表使用四个按钮输入:开始、停止、增量和清除(重置)。
  3. 开始输入使秒表开始以10Hz时钟速率递增(即每0.1秒计数一次);
  4. 停止输入使计数器停止递增,但使数码管显示当前计数器值;
  5. 每次按下按钮时,增量输入都会导致显示值增加一次,无论按住增量按钮多长时间;
  6. 复位/清除输入强制计数器值为零。

需求分析

四个按键作为开始、停止、增量、复位/清除的输入:

  1. 开始按键:按下时,秒表开始计时;
  2. 停止按键:按下时,秒表停止,并显示当前值;
  3. 增量按键:每次按下时,增加0.1秒,长按时仍然只会增加0.1秒;
  4. 复位/清除按键:按下时,秒表归零。

两个一位数码管用于显示秒表数值:

  1. 秒表每0.1秒更新一次,则需分频出10Hz的时钟频率;
  2. 9.9秒后翻转,则需将两个数码管重新赋值为0;

使用Verilog语言编写FPGA逻辑,实现按键控制和数码管显示。

在stepfpga中编译综合,并下载到小脚丫FPGA核心板上进行演示。

设计思路

硬件介绍

  1. 4个轻触按键;
  2. 4个拨动开关;
  3. 8个单色LED;
  4. 2个RGB三色灯;
  5. 2个共阴极数码管;
  6. 1个Type C接口;
  7. 2×20个排针。

引脚分配

代码展示

Main.v

   module Main(clk,seg_1,seg_2,rst,start,stop,increase);

input clk, rst;
input start, stop, increase;
output [8:0] seg_1, seg_2;

reg [3:0] segdata_1;
reg [3:0] segdata_2;
reg dis_start;
reg flog;

initial
begin
segdata_1 = 4'd0;
segdata_2 = 4'd0;
dis_start = 1;
flog = 1;
end

Display display(
.seg_data_1(segdata_1),
.seg_data_2(segdata_2),
.seg_led_1(seg_1),
.seg_led_2(seg_2)
);

wire clk1h;

divide #(.WIDTH(32), .N(1200000)) u2 (
.clk(clk),
.rst(rst),
.clkout(clk1h)
);

always @(posedge clk1h or negedge rst or negedge start or negedge stop)
begin

if (!rst)
begin
segdata_1 <= 4'd0;
segdata_2 <= 4'd0;
dis_start <= 1'd0;
end

else if (!start)
begin

dis_start <= 1'd1;
end

else if (!stop)
begin
dis_start <= 1'd0;
end

else if (!increase && dis_start == 0)
begin
if(flog)
begin
flog <= 1'd0;
if (segdata_2 != 4'd9)
begin
segdata_2 = segdata_2 + 4'd1;
end

else
begin
segdata_2 <= 4'd0;
segdata_1 = segdata_1 + 4'd1;
end

end

end

else if (dis_start == 1 && segdata_2 == 4'd9)
begin
segdata_2 <= 4'd0;
segdata_1 = segdata_1 + 4'd1;
end

else if (dis_start == 1)
begin
segdata_2 = segdata_2 + 4'd1;
if (segdata_1 == 4'd9 && segdata_2 == 4'd9)
begin
segdata_1 <= 4'd0;
segdata_2 <= 4'd0;
end

end

else if (increase)
begin
flog <= 1'd1;
end

end

endmodule

Display.v

module Display (seg_data_1,seg_data_2,seg_led_1,seg_led_2);

input [3:0] seg_data_1;
input [3:0] seg_data_2;
output [8:0] seg_led_1;
output [8:0] seg_led_2;

reg [8:0] seg1 [9:0];
reg [8:0] seg2 [9:0];

initial

begin
//带小数点
seg1[0] = 9'hbf;
seg1[1] = 9'h86;
seg1[2] = 9'hdb;
seg1[3] = 9'hcf;
seg1[4] = 9'he6;
seg1[5] = 9'hed;
seg1[6] = 9'hfd;
seg1[7] = 9'h87;
seg1[8] = 9'hff;
seg1[9] = 9'hef;

//不带小数点
seg2[0] = 9'h3f;
seg2[1] = 9'h06;
seg2[2] = 9'h5b;
seg2[3] = 9'h4f;
seg2[4] = 9'h66;
seg2[5] = 9'h6d;
seg2[6] = 9'h7d;
seg2[7] = 9'h07;
seg2[8] = 9'h7f;
seg2[9] = 9'h6f;
end

assign seg_led_1 = seg1[seg_data_1]; //连续赋值,这样输入不同四位数,就能输出对于译码的9位输出
assign seg_led_2 = seg2[seg_data_2];

endmodule

Divide.v

/*-------------------------------------*/
// Module name : Divide
// Author : STEP
// Description : 任意整数分频
// Web : www.stepfpga.com
/*-------------------------------------*/
module divide #
(
parameter WIDTH = 24, //计数器的位数,计数的最大值为 2**(WIDTH-1)
parameter N = 12_000_000 //分频系数,确保 N<2**(WIDTH-1)
)
(
input clk,
input rst,
output clkout
);
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) begin
if(!rst)
cnt_p <= 1'b0;
else if(cnt_p == (N-1))
cnt_p <= 1'b0;
else
cnt_p <= cnt_p + 1'b1;
end
//上升沿触发的分频时钟输出
always @(posedge clk or negedge rst)
begin
if(!rst)
clk_p <= 1'b0;
else if(cnt_p < (N>>1))
clk_p <= 1'b0;
else
clk_p <= 1'b1;
end
/*****************下降沿触发部分**************************************/
//下降沿触发时计数器的控制
always @(negedge clk or negedge rst)
begin
if(!rst)
cnt_n <= 1'b0;
else if(cnt_n == (N-1))
cnt_n <= 1'b0;
else
cnt_n <= cnt_n + 1'b1;
end
//下降沿触发的分频时钟输出,和clk_p相差半个clk时钟
always @(negedge clk or negedge rst)
begin
if(!rst)
clk_n <= 1'b0;
else if(cnt_n < (N>>1))
clk_n <= 1'b0;
else
clk_n <= 1'b1; //得到的分频时钟正周期比负周期多一个clk时钟
end
/*************************************************************************/
wire clk1 = clk; //当N=1时,直接输出clk
wire clk2 = clk_p; //当N为偶数也就是N的最低位为0,N[0]=0,输出clk_p
wire clk3 = clk_p & clk_n; //当N为奇数也就是N最低位为1,N[0]=1,输出clk_p&clk_n。

assign clkout = (N==1)? clk1:(N[0]? clk3:clk2);
endmodule

图片展示

主要问题

找不到语法错误的地方。


解决方法

复制代码到chat GPT中,它会给你修改。









附件下载
archive.zip
代码文件
团队介绍
山东农业大学
团队成员
杜德凯
山东农业大学电子信息科学与技术专业
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号