FPGA控制RGB灯WS2812B

news2025/5/11 17:06:40

文章目录

  • FPGA控制RGB灯WS2812B
    • 1、简介
      • 1.1水一水
      • 1.2程序完成目标
      • 1.3项目工程结构
    • 2、代码
    • 3、仿真代码
    • 4、结果展示

FPGA控制RGB灯WS2812B

1、简介

1.1水一水

最近在学习WS2812B手册,是一个简单的协议编写,做的时间也算是比较久,相对做出了一个较为完善的结果,在此作为分享

想查看协议的可以去到下列链接:

主要特点 (semiee.com)

1.2程序完成目标

1、有多种模式,按下按键key[0],切换模式

2、实现灯闪烁的速度核亮度的控制

3、实现动态显示FPGA四个字符

1.3项目工程结构

image-20230814184957589

2、代码

顶层模块:

module top(
    input wire clk,
    input wire rst_n,
    input wire[2:0] key,

    output wire din
);
wire ready_r;
wire enbale;
wire[2:0] key_r;
wire[23:0] data;
	led_ws_control inst_led_ws_control (
			.clk      (clk),
			.rst_n    (rst_n),
			.ready    (ready_r),
			.key      (key_r),

			.enable   (enable),
			.data_out (data)
		);
	led_ws inst_led_ws (
			.clk         (clk),
			.rst_n       (rst_n),
			.data_enable (enable),
			.data        (data),

			.ready       (ready_r),
			.din         (din)
		);

	key_debounce #(
			.N(3)
		) inst_key_debounce (
			.clk     (clk),
			.rst_n   (rst_n),
			.key_in  (key),
			.key_out (key_r)
		);

endmodule

按键消抖模块:

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// -----------------------------------------------------------------------------
// Author : 辣子鸡味的橘子,331197689@qq.com
// File   : key_debounce.v
// Create : 
// Revise : 
// Editor : sublime text4, tab size (4)
// Description:按键消抖模块
// -----------------------------------------------------------------------------
module key_debounce #(parameter N = 4,parameter TIME_20MS = 1000_000)(
    input wire clk,
    input wire rst_n,
    input wire[N-1:0] key_in,//四个按键信号输入

    output reg[N-1:0] key_out//四个按键信号消抖输出
);

reg[19:0] cnt;//20ms计数器
wire add_cnt;//计数开始
wire ent_cnt;//计数终止
wire nedge;//下降沿检测

reg[N-1:0] key_in_r0;//同步key_in输入信号
reg[N-1:0] key_in_r1;//延迟一个周期
reg[N-1:0] key_in_r2;//延迟两个周期

reg flag;//消抖开始标志信号

//计数器模块,当addent满足时开始计数,检测到下降沿重新计数,end_ent满足时停止计数,消抖完成
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt<=20'd0;
    end
    else if(add_cnt)begin
        if(ent_cnt)begin
            cnt<=20'd0;
        end
        else if(nedge)begin
            cnt<=20'd0;
        end
        else begin
            cnt<=cnt+1;
        end
    end
    else begin
        cnt<=cnt;
    end
end

assign add_cnt = flag;//计数开始条件
assign end_cnt = (cnt == TIME_20MS - 1)&&add_cnt;//终止结束条件,当满足计时到20ms,且满足计时条件时成立

//信号延时模块
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        key_in_r0<={N{1'b1}};
        key_in_r1<={N{1'b1}};
        key_in_r2<={N{1'b1}};
    end
    else begin
        key_in_r0<=key_in;
        key_in_r1<=key_in_r0;
        key_in_r2<=key_in_r1;
    end
end

//检测下降沿,当任意一个按键出现下降沿都会被检测到
assign nedge = |(~key_in_r1&key_in_r2);
assign podge = |(key_in_r1&~key_in_r2);
//消抖开始模块
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       flag<=1'b0;
    end
    else if(nedge|podge)begin//当出现下降沿开始消抖
        flag<=1'b1;
    end
    else if(end_cnt)begin//当end_cnt满足时停止消抖
        flag<=1'b0;
    end
    else begin
        flag<=flag;
    end
end

//输出信号赋值模块,当消抖完毕标志按键按下,出现一个脉冲信号表示按键按下
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       key_out<=4'b0000;
    end
    else if(end_cnt)begin
        key_out<=~key_in_r0;
    end
    else begin
       key_out<=4'b0000;
    end
end

endmodule

数据转化模块:

//==================================================================================================
//  Filename      : led_ws.v
//  Created On    : 2023-08-11 16:04:12
//  Last Modified : 2023-08-14 15:45:43
//  Revision      : 
//  Author        : 辣子鸡味的橘子
//  Email         : 331197689@qq.com
//
//  Description   : 这是led_ws模块,主要的作用是将传进来的数据用fifo进行存储,
//                  将fifo中存储的数据,转换为器件的码型输出
//
//==================================================================================================

module led_ws(
    input wire clk,
    input wire rst_n,
    input wire data_enable,
    input wire[23:0] data,//输入的RGB数据

    output wire ready,//一帧输出输出标志
    output reg din//转换过后的码
);
//定义变量参数
parameter MAX_RST = 'd20000;
parameter MAX_BIT = 'd23;
parameter MAX_NUM = 'd63;
parameter MAX_T = 'd60;
//目前的数字
wire[4:0] num;

wire din_t0;//0码
wire din_t1;//1码

reg[7:0] cnt_cyc;
wire add_cnt_cyc;
wire end_cnt_cyc;

reg[4:0] cnt_bit;
wire add_cnt_bit;
wire end_cnt_bit;

reg[7:0] cnt_num;
wire add_cnt_num;
wire end_cnt_num;

reg[15:0] cnt_rst;
wire add_cnt_rst;
wire end_cnt_rst;
//****************************************************************
//--两段式状态机
//****************************************************************
//---------<状态定义及状态转移条件>-----------------------------------
    parameter   IDLE    =   3'b001,
    			RESET   =   3'b010,
                DATA    =   3'b100;

    reg     [2:0]   state   ;

    wire   idle2reset;
    wire   reset2data;
    wire   data2idle;
//---------<状态转移>-----------------------------------
    always@(posedge clk or negedge rst_n)
        if(!rst_n)
            state <= IDLE;
        else case(state)
                IDLE    :  if(idle2reset)begin
                	state<=RESET;
                end

                RESET    :   if(reset2data)begin
                	state<=DATA;
                end

                DATA     :    if(data2idle)begin
                	state<=IDLE;
                end
                default:state<=state;
        endcase
//---------<状态转移条件赋值>-----------------------------------
    
	assign idle2reset = state == IDLE&&data_enable;
	assign reset2data = state == RESET&&end_cnt_rst;
	assign data2idle = state == DATA&&end_cnt_num;
//****************************************************************
//--fifoip核
//****************************************************************
wire fifo_wr;
wire fifo_rd;
wire fifo_empty;
wire fifo_full;
wire[5:0] fifo_usdw;
wire[23:0] fifo_q;
wire[23:0] fifo_data;
assign fifo_data = {data[15:8],data[23:16],data[7:0]};
assign fifo_wr = data_enable;//换成持续信号
assign fifo_rd = end_cnt_bit;

fifo	fifo_inst (
	.aclr ( ~rst_n ),
	.clock ( clk ),
	.data ( fifo_data ),
	.rdreq ( fifo_rd ),
	.wrreq ( fifo_wr ),
	.empty ( fifo_empty ),
	.full ( fifo_full ),
	.q ( fifo_q ),
	.usedw ( fifo_usdw )
	);


//---------<周期计数1200ns>-----------------------------------

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_cyc<='d0;
    end
    else if(add_cnt_cyc)begin
        if(end_cnt_cyc)begin
            cnt_cyc <='d0;
        end
        else begin
            cnt_cyc <= cnt_cyc + 1'b1;
        end
    end
    else begin
       cnt_cyc<=cnt_cyc;
    end
end
assign add_cnt_cyc = state == DATA;
assign end_cnt_cyc = add_cnt_cyc && cnt_cyc == MAX_T;

//---------<24bit计数>-----------------------------------

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_bit<='d0;
    end
    else if(add_cnt_bit)begin
        if(end_cnt_bit)begin
            cnt_bit <='d0;
        end
        else begin
            cnt_bit <= cnt_bit + 1'b1;
        end
    end
    else begin
       cnt_bit<=cnt_bit;
    end
end
assign add_cnt_bit = end_cnt_cyc;
assign end_cnt_bit = add_cnt_bit && cnt_bit == MAX_BIT;
//---------<64个像素计数>-----------------------------------

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_num<='d0;
    end
    else if(add_cnt_num)begin
        if(end_cnt_num)begin
            cnt_num <='d0;
        end
        else begin
            cnt_num <= cnt_num + 1'b1;
        end
    end
    else begin
       cnt_num<=cnt_num;
    end
end
assign add_cnt_num = end_cnt_bit;
assign end_cnt_num = add_cnt_num && cnt_num == MAX_NUM;
//---------<复位时间计数>-----------------------------------

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_rst<='d0;
    end
    else if(add_cnt_rst)begin
        if(end_cnt_rst)begin
            cnt_rst <='d0;
        end
        else begin
            cnt_rst <= cnt_rst + 1'b1;
        end
    end
    else begin
       cnt_rst<=cnt_rst;
    end
end
assign add_cnt_rst = state == RESET;
assign end_cnt_rst = add_cnt_rst && cnt_rst == MAX_RST;
//目前计数的数字
assign num = 23 - cnt_bit;
// assign din_t0 = cnt_cyc<2?1'b1:1'b0;
// assign din_t1 = cnt_cyc<3?1'b1:1'b0;
assign din_t0 = cnt_cyc<15?1'b1:1'b0;
assign din_t1 = cnt_cyc<30?1'b1:1'b0;
//---------<单项码赋值>-----------------------------------
always @(*) begin
    case(state)
        IDLE: din = 1'b0;
        RESET:din = 1'b0;
        DATA:begin
        	if(fifo_q[num] == 1'b1)begin
        		din = din_t1;
        	end
        	else begin
        		din = din_t0;
        	end
        end
        default:din = 1'b1;
    endcase
end

//准备条件
assign ready = state == IDLE;
endmodule

注意:其中设计到fifo的配置,下列我简单截取一下fifo中的配置

image-20230814183516700

image-20230814183529286

image-20230814183537567

数据控制模块:

//==================================================================================================
//  Filename      : led_ws_control.v
//  Created On    : 2023-08-11 16:08:30
//  Last Modified : 2023-08-14 17:22:26
//  Revision      : 
//  Author        : 辣子鸡味的橘子
//  Email         : 331197689@qq.com
//
//  Description   :这是控制模块,通过按键按下
//  1、按下key[0],显示三种状态,流水灯、彩虹灯、字体动态显示
//  2、按下key[1],控制亮度,按下亮度是减小,注意有限制
//  3、按下key[2],控制变换速度,三档2s、1s、0.5s
//==================================================================================================
module led_ws_control(
    input wire clk,
    input wire rst_n,
    input wire ready,//准备信号,由led_ws发出,当fifo值为空时发出,告诉控制端准备发送数据
    input wire[2:0] key,

    output wire enable,//使能信号,64个周期,写入63个数,给fifo进行寄存
    output wire[23:0] data_out//输出值
);
parameter TIME_2S = 'd99_999_999;
parameter TIME_1S = 'd49_999_999;
parameter TIME_500MS = 'd24_999_999;
wire[5:0] color_num;
wire[4:0] offect_num;
reg[2:0] flag_color;//控制彩灯闪烁
//亮度信号
reg[23:0] data_out_r1;
wire[23:0] data_out_r2;

reg[27:0] cnt_max;//灯光时间值
reg[2:0] flag_time;//灯光时间控制状态
//---------<状态定义及状态转移条件>-----------------------------------
    parameter   IDLE    =  3'b001 ,
                DATA    =   3'b010,
                DELAY    = 3'b100;

    reg     [2:0]   state   ;

    wire    idle2data;
    wire    data2delay;
    wire    delay2idle;
//****************************************************************
//--两段式状态机
//****************************************************************
reg[7:0] cnt;
wire add_cnt;
wire end_cnt;
//ram rom读写使能信号
wire ram_rd;
wire rom_rd;
//打拍延时信号
reg enable1;
reg enbale2;
reg[2:0] flag;//控制信号
reg[23:0] model1;//模式一
reg[23:0] model2;//模式二
wire[23:0] q_out;//ram的输出
wire[23:0] q_out1;//rom的输出

//---------<灯光亮度调节>-----------------------------------
//每次按下减小1/2,超过会复位
reg[3:0] cnt_light;
wire add_cnt_light;
wire end_cnt_light;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_light<='d0;
    end
    else if(add_cnt_light)begin
        if(end_cnt_light)begin
            cnt_light <='d0;
        end
        else begin
            cnt_light <= cnt_light + 1;
        end
    end
    else begin
       cnt_light<=cnt_light;
    end
end
assign add_cnt_light = key[1];
assign end_cnt_light = add_cnt_light && cnt_light == 'd5;
//---------<灯光速度控制>-----------------------------------
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        flag_time<=3'b100;
    end
    else if(key[2])begin
        flag_time<={flag_time[0],flag_time[2:1]};
    end
    else begin
        flag_time<=flag_time;
    end
end
//---------<灯光时间数据寄存>-----------------------------------
always @(*) begin
   case(flag_time)
        3'b001:cnt_max = TIME_500MS;
        3'b010:cnt_max = TIME_1S;
        3'b100:cnt_max = TIME_2S;
       default:cnt_max = TIME_2S;
   endcase
end
//灯光时间time计数器
reg[27:0] cnt_time;
wire add_cnt_time;
wire end_cnt_time;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_time<='d0;
    end
    else if(add_cnt_time)begin
        if(end_cnt_time)begin
            cnt_time <='d0;
        end
        else begin
            cnt_time <= cnt_time + 1'b1;
        end
    end
    else begin
       cnt_time<=cnt_time;
    end
end
assign add_cnt_time = state == DELAY;
assign end_cnt_time = add_cnt_time && cnt_time == cnt_max;

//****************************************************************
//--x坐标计数器
//****************************************************************
reg[2:0] cnt_x;
wire add_cnt_x;
wire end_cnt_x;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_x<='d0;
    end
    else if(add_cnt_x)begin
        if(end_cnt_x)begin
            cnt_x <='d0;
        end
        else begin
            cnt_x <= cnt_x + 1'b1;
        end
    end
    else begin
       cnt_x<=cnt_x;
    end
end
assign add_cnt_x = rom_rd;
assign end_cnt_x = add_cnt_x && cnt_x == 'd7;
//****************************************************************
//--y坐标计数器
//****************************************************************
reg[2:0] cnt_y;
wire add_cnt_y;
wire end_cnt_y;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_y<='d0;
    end
    else if(add_cnt_y)begin
        if(end_cnt_y)begin
            cnt_y <='d0;
        end
        else begin
            cnt_y <= cnt_y + 1'b1;
        end
    end
    else begin
       cnt_y<=cnt_y;
    end
end
assign add_cnt_y = end_cnt_x;
assign end_cnt_y = add_cnt_y && cnt_y == 'd7;
//****************************************************************
//--偏移量计数器
//****************************************************************
reg[5:0] cnt_offect;
wire add_cnt_offect;
wire end_cnt_offect;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_offect<='d0;
    end
    else if(add_cnt_offect)begin
        if(end_cnt_offect)begin
            cnt_offect <='d0;
        end
        else begin
            cnt_offect <= cnt_offect + 1'b1;
        end
    end
    else begin
       cnt_offect<=cnt_offect;
    end
end
assign add_cnt_offect = end_cnt_time;
assign end_cnt_offect = add_cnt_offect && cnt_offect == 'd31;

//更换灯光状态
//****************************************************************
//--闪烁灯效果
//****************************************************************
reg[2:0] cnt_state1;
wire add_cnt_state1;
wire end_cnt_state1;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt_state1<='d0;
    end
    else if(add_cnt_state1)begin
        if(end_cnt_state1)begin
            cnt_state1 <='d0;
        end
        else begin
            cnt_state1 <= cnt_state1 + 1'b1;
        end
    end
    else begin
       cnt_state1<=cnt_state1;
    end
end
assign add_cnt_state1 = end_cnt_time;
assign end_cnt_state1 = add_cnt_state1 && cnt_state1 == 'd8;

always @(*) begin
   case(cnt_state1)
        'd0:model1 <= 24'b00000000_11111110_00000000; // 红
        'd1:model1 <= 24'b11001101_11111110_00000000; // 橙
        'd2:model1 <= 24'b11111110_11111110_00000000; // 黄
        'd3:model1 <= 24'b11111110_00000000_00000000; // 绿
        'd4:model1 <= 24'b11111110_00000000_11111110; // 青
        'd5:model1 <= 24'b00000000_00000000_11111110; // 蓝
        'd6:model1 <= 24'b00000000_11001100_11001100; // 紫
        'd7:model1 <= 24'b11111110_11111110_11111110; // 白
        'd8:model1 <= 24'b11111111_11111111_11111111;   
       default:model1 = 24'hffffff;
   endcase
end

//更换灯光状态
//****************************************************************
//--流水灯效果
//****************************************************************
assign color_num = (cnt_y+cnt_offect)%8;
always @(*) begin
   case(color_num)
        'd7:model2 = 24'b00000000_11111110_00000000; // 红
        'd6:model2 = 24'b11001101_11111110_00000000; // 橙
        'd5:model2 = 24'b11111110_11111110_00000000; // 黄
        'd4:model2 = 24'b11111110_00000000_00000000; // 绿
        'd3:model2 = 24'b11111110_00000000_11111110; // 青
        'd2:model2 = 24'b00000000_00000000_11111110; // 蓝
        'd1:model2 = 24'b00000000_11001100_11001100; // 紫
        'd0:model2 = 24'b11111110_11111110_11111110; //白
       default:model2 = 24'hffffff;
   endcase
end

//---------<灯光控制信号>-----------------------------------
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        flag<=3'b001;
    end
    else if(key[0])begin
        flag<={flag[1:0],flag[2]};
    end
    else begin
        flag<=flag;
    end
end
//计数器,用于计算发送数据的个数
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt<='d0;
    end
    else if(add_cnt)begin
        if(end_cnt)begin
            cnt <= 'd0;
        end
        else begin
            cnt <= cnt + 1'b1;
        end
    end
    else begin
       cnt<=cnt;
    end
end
assign add_cnt = state == DATA;
assign end_cnt = add_cnt && cnt == 'd63;

//****************************************************************
//--延时打拍使能信号,因为ram读取的信号有两拍的延时
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
      	enable1<=1'b0;
      	enbale2<=1'b0;
    end
    else begin
        enable1<=ram_rd;
        enbale2<=enable1;
    end
end


//---------<状态转移>-----------------------------------
    always@(posedge clk or negedge rst_n)
        if(!rst_n)
            state <= IDLE;
        else case(state)
                IDLE    :  if(idle2data)state<=DATA;
                DATA    :  if(data2delay)state<=DELAY;
                DELAY    :  if(delay2idle)state<=IDLE;
                default :   state <= IDLE;
        endcase
//---------<状态转移条件赋值>-----------------------------------
    assign  idle2data = ready&&state==IDLE;
    assign 	data2delay = end_cnt&&state==DATA;
    assign  delay2idle = end_cnt_time&&state==DELAY;
//****************************************************************
//--灯光状态3
//****************************************************************
assign offect_num = cnt_offect+cnt_x;
rom rom_inst (
    .aclr ( ~rst_n ),
    .address ( cnt_y*32+offect_num ),
    .clock ( clk ),
    .rden ( rom_rd ),

    .q ( q_out1 )
    );

//读写使能定义条件
assign ram_rd = state == DATA;
assign rom_rd = state == DATA;
assign enable = (flag == 3'b100)?enbale2:rom_rd;
//data_out_r1输出值定义
always @(*) begin
   case(flag)
       3'b001:data_out_r1 = model1;
       3'b010:data_out_r1 = model2;
       3'b100:begin
           if(enbale2)begin
               //data_out_r1 = q_out;//RAM显示
               data_out_r1 = q_out1;//ROM显示
           end
           else begin
               data_out_r1 = 24'h000000;
           end
       end
       default:data_out_r1 = 24'h000000;
   endcase
end

//---------<亮度值控制>-----------------------------------
assign data_out_r2[7:0] = cnt_light == 0?data_out_r1[7:0]:(data_out_r1[7:0]>>cnt_light);
assign data_out_r2[15:8] = cnt_light == 0?data_out_r1[15:8]:(data_out_r1[15:8]>>cnt_light);
assign data_out_r2[23:16] = cnt_light == 0?data_out_r1[23:16]:(data_out_r1[23:16]>>cnt_light);

assign data_out = data_out_r2;
endmodule

这里涉及到了rom的配置,我这里简单演示

image-20230814184456505

image-20230814184504786

image-20230814184518894

mif文件内容:

-- Copyright (C) 2015-Endless, CrazyBird Corporation
-- Thank you for use CrazyBird's design tools

DEPTH = 256;
WIDTH = 24;
ADDRESS_RADIX = UNS;
DATA_RADIX = HEX;

CONTENT BEGIN

0 : ed1c24;
1 : ed1c24;
2 : ed1c24;
3 : ed1c24;
4 : ed1c24;
5 : 000000;
6 : 000000;
7 : 000000;
8 : ed1c24;
9 : ed1c24;
10 : ed1c24;
11 : ed1c24;
12 : ed1c24;
13 : 000000;
14 : 000000;
15 : 000000;
16 : ed1c24;
17 : ed1c24;
18 : ed1c24;
19 : ed1c24;
20 : 000000;
21 : 000000;
22 : 000000;
23 : 000000;
24 : 000000;
25 : 000000;
26 : ed1c24;
27 : ed1c24;
28 : ed1c24;
29 : 000000;
30 : 000000;
31 : 000000;
32 : ed1c24;
33 : 000000;
34 : 000000;
35 : 000000;
36 : 000000;
37 : 000000;
38 : 000000;
39 : 000000;
40 : ed1c24;
41 : 000000;
42 : 000000;
43 : 000000;
44 : ed1c24;
45 : 000000;
46 : 000000;
47 : 000000;
48 : ed1c24;
49 : 000000;
50 : 000000;
51 : 000000;
52 : 000000;
53 : 000000;
54 : 000000;
55 : 000000;
56 : 000000;
57 : 000000;
58 : ed1c24;
59 : 000000;
60 : ed1c24;
61 : ed1c24;
62 : 000000;
63 : 000000;
64 : ed1c24;
65 : 000000;
66 : 000000;
67 : 000000;
68 : 000000;
69 : 000000;
70 : 000000;
71 : 000000;
72 : ed1c24;
73 : 000000;
74 : 000000;
75 : 000000;
76 : ed1c24;
77 : 000000;
78 : 000000;
79 : 000000;
80 : ed1c24;
81 : 000000;
82 : 000000;
83 : 000000;
84 : 000000;
85 : 000000;
86 : 000000;
87 : 000000;
88 : 000000;
89 : 000000;
90 : ed1c24;
91 : 000000;
92 : 000000;
93 : ed1c24;
94 : 000000;
95 : 000000;
96 : ed1c24;
97 : ed1c24;
98 : ed1c24;
99 : ed1c24;
100 : ed1c24;
101 : 000000;
102 : 000000;
103 : 000000;
104 : ed1c24;
105 : ed1c24;
106 : ed1c24;
107 : ed1c24;
108 : ed1c24;
109 : 000000;
110 : 000000;
111 : 000000;
112 : ed1c24;
113 : 000000;
114 : 000000;
115 : ed1c24;
116 : ed1c24;
117 : ed1c24;
118 : ed1c24;
119 : 000000;
120 : 000000;
121 : ed1c24;
122 : ed1c24;
123 : 000000;
124 : 000000;
125 : ed1c24;
126 : ed1c24;
127 : 000000;
128 : ed1c24;
129 : 000000;
130 : 000000;
131 : 000000;
132 : 000000;
133 : 000000;
134 : 000000;
135 : 000000;
136 : ed1c24;
137 : 000000;
138 : 000000;
139 : 000000;
140 : 000000;
141 : 000000;
142 : 000000;
143 : 000000;
144 : ed1c24;
145 : 000000;
146 : 000000;
147 : ed1c24;
148 : 000000;
149 : 000000;
150 : ed1c24;
151 : 000000;
152 : 000000;
153 : ed1c24;
154 : ed1c24;
155 : ed1c24;
156 : ed1c24;
157 : ed1c24;
158 : ed1c24;
159 : 000000;
160 : ed1c24;
161 : 000000;
162 : 000000;
163 : 000000;
164 : 000000;
165 : 000000;
166 : 000000;
167 : 000000;
168 : ed1c24;
169 : 000000;
170 : 000000;
171 : 000000;
172 : 000000;
173 : 000000;
174 : 000000;
175 : 000000;
176 : ed1c24;
177 : 000000;
178 : 000000;
179 : ed1c24;
180 : 000000;
181 : 000000;
182 : ed1c24;
183 : 000000;
184 : 000000;
185 : ed1c24;
186 : 000000;
187 : 000000;
188 : 000000;
189 : 000000;
190 : ed1c24;
191 : ed1c24;
192 : ed1c24;
193 : 000000;
194 : 000000;
195 : 000000;
196 : 000000;
197 : 000000;
198 : 000000;
199 : 000000;
200 : ed1c24;
201 : 000000;
202 : 000000;
203 : 000000;
204 : 000000;
205 : 000000;
206 : 000000;
207 : 000000;
208 : ed1c24;
209 : 000000;
210 : 000000;
211 : 000000;
212 : 000000;
213 : ed1c24;
214 : ed1c24;
215 : 000000;
216 : ed1c24;
217 : ed1c24;
218 : 000000;
219 : 000000;
220 : 000000;
221 : 000000;
222 : 000000;
223 : ed1c24;
224 : ed1c24;
225 : 000000;
226 : 000000;
227 : 000000;
228 : 000000;
229 : 000000;
230 : 000000;
231 : 000000;
232 : ed1c24;
233 : 000000;
234 : 000000;
235 : 000000;
236 : 000000;
237 : 000000;
238 : 000000;
239 : 000000;
240 : ed1c24;
241 : ed1c24;
242 : ed1c24;
243 : ed1c24;
244 : ed1c24;
245 : ed1c24;
246 : 000000;
247 : 000000;
248 : ed1c24;
249 : 000000;
250 : 000000;
251 : 000000;
252 : 000000;
253 : 000000;
254 : 000000;
255 : ed1c24;

END;

**注意:**mif文件要放在工程目录下,不然读取不到数据

3、仿真代码

这个仿真代码很简单,注意各个模块中的参数值就行

`timescale 1ns/1ns
module top_tb();

reg clk;
reg rst_n;
reg[2:0] key;
wire din;
parameter SYS_CLK = 20;
always #(SYS_CLK/2) clk = ~clk;

initial begin
    clk=1'b0;
    rst_n=1'b0;
    #(2*SYS_CLK);
    rst_n=1'b1;
    
end
defparam inst_top.inst_led_ws_control.TIME_500MS = 1000;
defparam inst_top.inst_led_ws_control.TIME_1S = 2000;
defparam inst_top.inst_led_ws_control.TIME_2S = 4000;
initial begin
    //彩虹灯模式
    key = 3'b111;
    #(SYS_CLK*50);
    key = 3'b110;
    #(SYS_CLK*50);
    key = 3'b111;
    #(50*SYS_CLK);
    //字体动态显示模式
    //  key = 3'b111;
    // #(SYS_CLK*50);
    // key = 3'b110;
    // #(SYS_CLK*50);
    // key = 3'b111;
    // #(50*SYS_CLK);
    //流水灯模式
    //  key = 3'b111;
    // #(SYS_CLK*50);
    // key = 3'b110;
    // #(SYS_CLK*50);
    // key = 3'b111;
    // #(50*SYS_CLK);
    #2000000;
    $stop;
end
top inst_top (.clk(clk), .rst_n(rst_n), .key(key), .din(din));

endmodule

4、结果展示

1、闪烁灯:

QQ视频20230814185745_-middle-original

2、彩虹灯

QQ视频20230814185741_-middle-original

3、字体动态显示

QQ视频20230814185735_-middle-original

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/877550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

00-认识C++

2、认识C 2.1、例子 一个简单的C例子 #include <iostream>int main() {using namespace std; //使用名称空间cout << "Com up and C me some time.";cout << endl; //换行符&#xff0c;还可以cout<<"\n";cout <…

【JAVA】集合(Collection、Map)

集合和数组都是容器 数组&#xff1a;类型确定&#xff0c;长度固定&#xff0c;可以存储基本类型和引用类型的数据 集合&#xff1a;类型可以不固定&#xff0c;大小可变&#xff0c;只能存储引用数据类型的数据 Collection单列单列集合&#xff0c;每个元素只包含一个值Ma…

伴随矩阵的特征值跟原矩阵特征值居然有关系!!!附证明

文章目录 论点&#xff1a;A与其伴随矩阵的特征值相乘等于|A|证明证明证明中涉及的相关定理&#xff1a;1.逆矩阵与伴随矩阵的关系2.A可逆时&#xff0c;A的逆矩阵的特征值是原矩阵特征值的倒数 论点&#xff1a;A与其伴随矩阵的特征值相乘等于|A| 证明 证明 证明中涉及的相关…

html css实现爱心

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 爱心 */.lo…

基于Matlab实现小偷体貌识别仿真(附上源码+数据集)

小偷体貌识别是一种应用于安全领域的重要技术&#xff0c;它利用计算机视觉和机器学习的方法&#xff0c;通过对监控视频中的人体特征进行提取和分析&#xff0c;来识别出可能的小偷。在本文中&#xff0c;我们将介绍如何使用Matlab实现小偷体貌识别的仿真。 文章目录 介绍部分…

测牛学堂:软件测试工程师都要懂的软件开发模型总结

软件开发模型之快速原型 之前跟大家介绍了最早期的瀑布模型。今天聊一下快速原型模型。 快速原型&#xff0c;在初步确定用户需求之后&#xff0c;快速构造出一个原型项目&#xff0c;可以跟用户展示软件的功能&#xff0c;用户根据原型进行评审&#xff0c;提出更进一步的细…

JavaWeb-Servlet服务连接器(终)

上一篇文章JavaWeb-Servlet服务连接器&#xff08;三&#xff09;_Alphamilk的博客-CSDN博客 目录 1.ServletContext通信 会话技术Cookie与Session 1.Cookie 2.Session 1.ServletContext通信 概念&#xff1a;代表了整个web应用&#xff0c;用于与服务器实现通信 可以通…

6.2 口令破解攻击

数据参考&#xff1a;CISP官方 目录 口令安全问题口令破解攻击口令破解安全防护口令使用安全管理 一、口令安全问题 什么是口令 身份验证的机制&#xff0c;俗称 “密码"&#xff0c;对应英文单词为 password成本较低&#xff0c;得到广泛应用信息安全中的 “密码”…

基于 Nginx All In One 的 Outline Wiki 部署方法

1. Outline 简介 官网&#xff1a;https://www.getoutline.com/ Outline 是一个开源的知识库和团队协作工具&#x1f9e0;&#xff0c;旨在帮助团队共享、组织和协作文档&#x1f4dd;。它提供了一个简洁的界面&#xff0c;使用户能够轻松创建、编辑和查看文档。 以下是 Out…

sudo免密码设置以及设置失败解决方法

使用sudo visudo修改\etc\sudoers文件 打开后有很多已有的设置大致格式username ALL(ALL:ALL) ALL&#xff0c;都不要动&#xff01; 在文件结尾加上一句话&#xff1a; username ALL(ALL:ALL) NOPASSWD: ALLusername就是目前你这个账户的名字&#xff0c;开机时会输密码登录…

Nginx访问日志及巡检统计

一、前言 二、词汇解释 2.1、pv和uv的区别 PV&#xff08;Page View访问量/也卖弄浏览数&#xff09;&#xff1a;指在一定统计周期内&#xff0c;用户每次刷新网页一次即计算一次。PV高不一定代表来访者多:PV与来访者的数量成正比&#xff0c;但是PV并不直接决定页面的真实来…

同样的字符串,有一些事长度为3,有一些长度为2,导致Convert.ToByte(macStringArray[i], 16);出错

同样的字符串&#xff0c;有一些事长度为3&#xff0c;有一些长度为2,导致Convert.ToByte(macStringArray[i], 16);出错。 最后&#xff0c;把长度为2的复制过去&#xff0c;就好了。 要复制“1C- 只复制1C不行 { “pc101”:“1C-69-7A-BD-05-C4”, “pc102”:“1C-69-7A-BD…

Selenium自动化测试实战之自动化测试基础

自动化测试概念 是把以人为驱动的测试转化为机器执行的一种过程&#xff0c;它是一种以程序测试程序的过程。 自动化只是测试方式&#xff0c;跟测试阶段无关。 可以把任何测试工作写一个程序自动化实现都可以称为自动化测试。 selenium自动化测试&#xff1a;2023最新的Sele…

docker可视化工具Portainer

1:Portainer简介 Portainer是一个docker可视化管理工具&#xff0c;可以非常方便地管理docker镜像容器。官网地址&#xff1a;https://www.portainer.io/ 注&#xff1a;现在Portainer有BE&#xff08;收费&#xff09;和CE&#xff08;免费&#xff09;版本&#xff0c;安装的…

答疑:Arduino IDE配置其他开发板下载速度慢

基于案例&#xff1a;Linux环境Arduino IDE中配置ATOM S3 通常&#xff0c;网络问题较多&#xff0c;可以使用一些技巧。 https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json 没有配置&#xff0c;不支持M5Stack&#xff08;ESP32&…

SpringCloud教程(上)

目录 一、微服务架构理论入门 1.1、什么是微服务&#xff1f; 1.2、微服务简单总结 1.3、微服务的优缺点 1.4、微服务、分布式、集群的区别 1.5、SpringCloud停更替换技术说明 二、微服务架构编码构建 2.1、微服务cloud整体聚合父工程Project 2.1.1、New Project 2.1…

【【萌新的STM32学习-9】】

萌新的STM32学习-9 我们在使用某个外设&#xff0c;必须线使能该外设时钟 SYSTEM 文件夹里面的代码由正点原子提供&#xff0c;是 STM32F1xx 系列的底层核心驱动函数&#xff0c; 可以用在 STM32F1xx 系列的各个型号上面&#xff0c;方便大家快速构建自己的工程。本章&#xf…

这所985非常难考,却无数人趋之若鹜!

一、学校及专业介绍 厦门大学&#xff08;Xiamen University&#xff09;&#xff0c;简称厦大&#xff08;XMU&#xff09;&#xff0c;位于福建省厦门市&#xff0c;位列国家“双一流”、“985工程”、“211工程”重点建设高校。 1.1 招生情况 厦门大学初试考847信号与系统…

Android AOSP源码编译——AOSP整编(二)

切换到源码目录下执行下面命令 1、初始化环境 . build/envsetup.sh //清除缓存 make clobber2、选择编译目标 lunchAOSP 预制了很多 Product。这里为了简单我们先不用真机&#xff0c;而是选择模拟器的方式&#xff0c;对于 x86_64 模拟器&#xff0c;我们选择的是 aosp_x86…

DevOps系列文章 之 Gitlab+Docker自动部署SpringBoot

1.环境要求 以下服务器的操作系统均为Centos7 服务器A&#xff1a;Gitlab服务器B&#xff1a;GitlabRunner、Docker、docker-compose、Java1.8、maven3.6.3、git ps&#xff1a;这里可以把服务器B的GitlabRunner、Java1.8、maven3.6.3、git单独提出来&#xff0c;独立部署&a…