本文主要是介绍FPGA课程设计(拨码控制流水灯),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
基本要求:以十赫兹的频率,点亮实验开发板上的发光二极管,显示过程中各个点亮的发光二极管的亮度呈现出明暗变化,形似呼吸。开关0 向下系统复位,灯全灭。开关0向上,LED呈现呼吸状显示。(利用pwm)
扩展部分:
分组显示两组不同渐变周期的呼吸灯,Key0控制LED4~LED0显示, KEY1 控制LED9~LED5显示,渐变周期由开关1~开关9输入,同时数码管分别显示2组呼吸灯对应周期数。
module led
(
//数据的输入input wire sys_clk ,input wire sys_rst_n , input wire [9:0] sw_in , input wire key_in1 , input wire key_in2 , //led的输出output wire [9:0] led_out ,//前三个数码管显示频率output wire [6:0] ge1 ,output wire [6:0] shi1 ,output wire [6:0] bai1 ,//后三个数码管显示频率output wire [6:0] ge2 ,output wire [6:0] shi2 ,output wire [6:0] bai2 );wire [8:0] data_in1 ;
wire [8:0] data_in2 ;
wire [10: 0] bcd1 ;
wire [10: 0] bcd2 ;//key1和key2 控制输入的频率
ctrl ctrl_inst
(.sys_clk (sys_clk) ,.sys_rst_n (sys_rst_n) , .sw_in (sw_in) , .key_in1 (key_in1) , .key_in2 (key_in2) ,.data_in1 (data_in1) ,.data_in2 (data_in2) );//开关输入的二进制数,转换为BCD码用于数码管显示
binTobcd binTobcd_inst1
( .bin (data_in1), // binary.bcd (bcd1)
);binTobcd binTobcd_inst2
( .bin (data_in2), // binary.bcd (bcd2)
);//led的输出breath_led breath_led_inst1
(.sys_clk (sys_clk ),.sys_rst_n (sys_rst_n),.data (data_in1),.led_out (led_out[4:0] )
);breath_led breath_led_inst2
(.sys_clk (sys_clk ),.sys_rst_n (sys_rst_n),.data (data_in2),.led_out (led_out[9:5] )
);//数码管显示seg seg_int1
(.sys_clk (sys_clk) ,.sys_rst_n (sys_rst_n) ,.sw0 (sw_in[0]) ,.bcd (bcd1) ,.ge (ge1) ,.shi (shi1) ,.bai (bai1)
);seg seg_int2
(.sys_clk (sys_clk) ,.sys_rst_n (sys_rst_n) ,.sw0 (sw_in[0]) ,.bcd (bcd2) ,.ge (ge2) ,.shi (shi2) ,.bai (bai2)
);module breath_led(input wire sys_clk , //系统时钟50Mhzinput wire sys_rst_n , //key3全局复位input wire [8:0] data ,//获得控制权寄存的数据output reg [4:0] led_out //led的输出
);reg [9:0] cnt_1s ;
reg [9:0] cnt_1ms ;
reg [5:0] cnt_1us ;
reg cnt_en ;//PWM脉宽调制呼吸流水,的几个参数来调制,和改变频率
parameter CNT_1US_MAX = 6'd49 ;
parameter CNT_1MS_MAX = 10'd999;
parameter CNT_1S_MAX = 10'd999 ;//cnt_1us:1us计数器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1us <= 6'd0;else if(cnt_1us == CNT_1US_MAX)cnt_1us <= 6'd0;elsecnt_1us <= cnt_1us + 6'd1;//cnt_1ms:1ms计数器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1ms <= 10'd0;else if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_1ms <= 10'd0;else if(cnt_1us == CNT_1US_MAX)cnt_1ms <= cnt_1ms + 10'd1;elsecnt_1ms <= cnt_1ms;//cnt_1s:1s计数器以及用1S来作为基础,通过1/data来获得新的频率让led的闪亮
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1s <= 10'd0;else if(data == 9'd0)cnt_1s <= 10'd0;else if((cnt_1s == CNT_1S_MAX / data) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_1s <= 10'd0;else if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_1s <= cnt_1s + 10'd1;elsecnt_1s <= cnt_1s;//cnt_1s:1s计数器以及用1S来作为基础,通过1/data来获得新的频率让led的闪亮的使能信号
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_en <= 1'b0;else if(data == 9'd0)cnt_en <= 1'b0;else if((cnt_1s == CNT_1S_MAX / data) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_en <= ~cnt_en;elsecnt_en <= cnt_en;//利用PWM脉宽调制呼吸流水
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)led_out <= 5'b00000;else if(data == 9'd0)led_out <= 5'b00000;else if(((cnt_en == 1'b0) && (cnt_1ms <= cnt_1s)) || ((cnt_en == 1'b1) && (cnt_1ms > cnt_1s)))led_out <= 5'b00000;elseled_out <= 5'b11111;endmodulemodule ctrl
(input wire sys_clk ,//输入50mhz的时钟信号input wire sys_rst_n , //复位信号input wire [9:0] sw_in , //拨码开关input wire key_in1 , // 按键控制input wire key_in2 ,//按键控制output reg [8:0] data_in1 ,//输出的数据output reg [8:0] data_in2 //输出的数据);reg begin_reg ;//开始的标志,开始时10hz的频率
reg sw0_reg ;//sw[0]的延时一拍
reg key_in1_reg ;//按键1控制后面的数据
reg key_in2_reg ; //按键2控制前面的数据wire sw0_flag ; //SW[0]拨动了的标志信号//最开SW0拨上去就赋值给数据初始值10hz,按下按键后跳转
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)sw0_reg <= 1'd0;elsesw0_reg <= sw_in[0];assign sw0_flag = ((sw_in[0])&&(~ sw0_reg));always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)begin_reg <= 1'd0;else if(key_in1 == 1'd0 ||key_in2 == 1'd0)begin_reg <= 1'd0;else if(sw0_flag == 1'd1)begin_reg <= ~ begin_reg;elsebegin_reg <= begin_reg;// 按下按键获得对前后数据的控制权
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)key_in1_reg <= 1'd0;else if(sw_in[0] == 1'd0)key_in1_reg <= 1'd0;else if(key_in2 == 1'd0)key_in1_reg <= 1'd0; else if(sw_in[0] == 1'd1 && key_in1 == 1'd0)key_in1_reg <= 1'd1;elsekey_in1_reg <= key_in1_reg;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)key_in2_reg <= 1'd0;else if(sw_in[0] == 1'd0)key_in2_reg <= 1'd0;else if(key_in1 == 1'd0)key_in2_reg <= 1'd0;else if(sw_in[0] == 1'd1 && key_in2 == 1'd0)key_in2_reg <= 1'd1;elsekey_in2_reg <= key_in2_reg;//把数据传输给寄存器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_in1 <= 9'd0;else if(sw_in[0] == 1'd0)data_in1 <= 9'd0;else if(sw_in[0] == 1'd1 && begin_reg == 1'd1)data_in1 <= 9'd10;else if(key_in1_reg == 1'd1)data_in1 <= sw_in[9:1] ;elsedata_in1 <= data_in1;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_in2 <= 9'd0;else if(sw_in[0] == 1'd0)data_in2 <= 9'd0;else if(sw_in[0] == 1'd1 && begin_reg == 1'd1)data_in2 <= 9'd10;else if(key_in2_reg == 1'd1)data_in2 <= sw_in[9:1] ;elsedata_in2 <= data_in2;endmodulemodule seg
(input wire sys_clk ,//系统时钟50Mhzinput wire sys_rst_n ,//key3全局复位input wire sw0 ,//sw0的拨码输入input wire [10:0] bcd ,//转换后的BCd码output reg [6:0] ge ,//个位的输出output reg [6:0] shi ,//十位的输出output reg [6:0] bai //百位的输出
);//个位的输出
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)ge <= 7'b1_111_111;else if(sw0 == 1'd0)ge <= 7'b1_111_111;else case(bcd[3:0])
4'b0000:ge <= 7'b1_000_000;
4'b0001: ge <= 7'b1_111_001;
4'b0010: ge <= 7'b0_100_100;
4'b0011: ge <= 7'b0_110_000;
4'b0100: ge <= 7'b0_011_001;
4'b0101: ge <= 7'b0_010_010;
4'b0110: ge <= 7'b0_000_010;
4'b0111: ge <= 7'b1_111_000;
4'b1000: ge <= 7'b0_000_000;
4'b1001: ge <= 7'b0_010_000;
default: ge <= 7'b1_000_000;
endcase//十位的输出
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)shi <= 7'b1_111_111;else if(sw0 == 1'd0)shi <= 7'b1_111_111;else case(bcd[7:4])
4'b0000:shi <= 7'b1_000_000;
4'b0001:shi <= 7'b1_111_001;
4'b0010:shi <= 7'b0_100_100;
4'b0011:shi <= 7'b0_110_000;
4'b0100:shi <= 7'b0_011_001;
4'b0101:shi <= 7'b0_010_010;
4'b0110:shi <= 7'b0_000_010;
4'b0111:shi <= 7'b1_111_000;
4'b1000:shi <= 7'b0_000_000;
4'b1001:shi <= 7'b0_010_000;
default: shi <= 7'b1_000_000;
endcase//百位的输出
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)bai <= 7'b1_111_111;else if(sw0 == 1'd0)bai <= 7'b1_111_111;else case(bcd[10:8])
3'b000:bai <= 7'b1_000_000;
3'b001: bai <= 7'b1_111_001;
3'b010: bai <= 7'b0_100_100;
3'b011: bai <= 7'b0_110_000;
3'b100: bai <= 7'b0_011_001;
3'b101: bai <= 7'b0_010_010;
3'b110: bai <= 7'b0_000_010;
3'b111: bai <= 7'b1_111_000;
/* 4'b1000: shi <= 7'b0_000_000;
4'b1001: shi <= 7'b0_010_000; */
default: bai <= 7'b1_000_000;
endcaseendmodulemodule binTobcd(input [8:0] bin,//二进制数output [10:0] bcd//BCD码);reg [3:0] ones;
reg [3:0] tens;
reg [2:0] hundreds;
integer i;//移3进位的算法
always @(*) beginones = 4'd0;tens = 4'd0;hundreds = 3'd0;for(i = 8; i >= 0; i = i - 1) beginif (ones >= 4'd5) ones = ones + 4'd3;if (tens >= 4'd5) tens = tens + 4'd3;if (hundreds >= 4'd5) hundreds = hundreds + 4'd3;hundreds = {hundreds[1:0],tens[3]};tens = {tens[2:0],ones[3]};ones = {ones[2:0],bin[i]};endend assign bcd = {hundreds, tens, ones};endmodule
测试代码:
`timescale 1ns/1ns //时间参数
module tb_led();reg sys_clk ;//模拟时钟信号
reg sys_rst_n ; //模拟复位信号
reg [9:0] sw_in ; //模拟拨码
reg key_in1 ; //模拟按键
reg key_in2 ;//模拟按键wire [9:0]led_out ;//模拟灯的输出wire [6:0] ge1 ;
wire [6:0] shi1 ;
wire [6:0] bai1 ;wire [6:0] ge2 ;
wire [6:0] shi2 ;
wire [6:0] bai2 ;//模拟输入
initialbeginsys_clk = 1'b1;//开始的赋值sys_rst_n <= 1'b0;sw_in <= 10'd0;key_in1 <= 1'b1;key_in2 <= 1'b1;#20sys_rst_n <= 1'b1;//复位#5_000_00sw_in[0] <= 1'b1;//SW0拨上#1_000_000_000key_in1 <= 1'b0;//按下按键key0#200key_in1 <= 1'b1;#200 sw_in[9:1] <= 9'b0_0000_0001;//拨码输入1hz#1_000_000_000sw_in[9:1] <= 9'b1_0001_0001;//等1s拨码输入频率#1_000_000_000sw_in[9:1] <= 9'b1_1011_0001;//等1s拨码输入频率#5000key_in2 <= 1'b0;//按下key1#200key_in2 <= 1'b1;#500_000_000key_in1 <= 1'b0;//等0.5s,按下key0#200key_in1 <= 1'b1;#1_000_000_000sw_in[9:1] <= 9'b0_0000_0000;//等1s拨码输入频率#1_000_000_000sw_in[9:1] <= 9'b0_0000_0001;//等1s拨码输入频率#1_000_000_000sw_in[0] <= 1'b0;//等1s拨码sw0拨下endalways #10 sys_clk = ~sys_clk;//时钟生成//调用模块
led led_inst
(.sys_clk (sys_clk) ,.sys_rst_n (sys_rst_n) , .sw_in (sw_in) , .key_in1 (key_in1) , .key_in2 (key_in2) , .led_out (led_out) ,.ge1 (ge1) ,.shi1 (shi1) ,.bai1 (bai1) ,.ge2 (ge2) ,.shi2 (shi2) ,.bai2 (bai2));
endmodule
这篇关于FPGA课程设计(拨码控制流水灯)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!