英特尔FPGA实训day3

学习内容:

今天学习了led流水灯,以及跑马灯的实现,有限状态机知识的回顾,更重要的是呼吸灯的实现。值得肯定的是,今天对fpga的代码实现有了进一步认识,基本掌握了如何去书写的基本结构,以及仿真文件的一些参数的含义。但不足的是,今天对于呼吸灯和流水灯的结合实现,没能顺利完成,当然,在这其中也经过很多思考,也是很值得肯定的。

困难的产生与解决:

1. 今天发现有些同学编译不成功,说mutil..... 这种一般是,写了多个相同的变量在不同的地方被赋值。特别是多个always中,因为always之间是并列进行的(即:可理解为多线程的)。

2. 呼吸灯的实现,开始没懂。其实现其实比较巧妙,虽然这个普通的led灯没有多个电平的分级,但可以实现在时间上的分级,即 持续高电平10ns和持续100ns 其亮度是不一样的。这其中实现很巧妙,很值得反复琢磨。

还有今天把实现流水灯与呼吸灯结合的任务理解为了 跑马灯与呼吸灯结合,这难度却不料想是要大得多的。但说实话也很期待实现。

疑问产生:

        wire类型变量和寄存器reg变量有什么区别,特别是在使用的时候有什么区别?

接下来打算:

后面将进一步思考流水灯和呼吸灯的实现,以及进一步思考跑马灯和呼吸灯结合,看能实现不。还有就是,尽量把呼吸灯的实现逻辑,过程细节,能想清楚。

收获杂记:

仿真文件中:

步骤① ,是传入参数值的方式

前面那个 .TIME 是fsm_led 中的参数名字  括号中的TIME是该仿真文件中的文件

 

下面还有就是今天实现的一些代码,包括流水灯,跑马灯,呼吸灯,流水灯与呼吸灯结合。

其中实现方法多种多样,比如流水灯,可以通过case列举的方式实现定时移位,可以用移位<<符号进行状态移位,还有用状态机,进行状态转移(文中的方法就是用的有限状态机)

(有限状态机:就是给一个初始状态,然后就会在这个状态内相互转换,实质也就是把所有情况列举出,然后给予一定转化条件,这种思考设计方式就叫有限状态机设计(个人理解))

流水灯代码:(有限状态机)

module fsm_led(
    input clk,
    input rst_n,

    output reg[3:0] led
);

parameter TIME = 24 'd9_999_999;//计数器的挤时上限
//状态空间
parameter S_LED0 = 2'd0;
parameter S_LED1 = 2'd1;
parameter S_LED2 = 2'd2;
parameter S_LED3 = 2'd3;

//四个LED的值
parameter LED0 = 4'b0001;
parameter LED1 = 4'b0010;
parameter LED2 = 4'b0100;
parameter LED3 = 4'b1000;


reg [1:0] state;//保存正处于的状态

reg [23:0] cnt ;//计数寄存器

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt <= 24 'd0;
    end
    else if (cnt == TIME) begin
        cnt <=24'd0;
    end
    else begin
        cnt <= cnt + 1'd1;
    end
end
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        state <= S_LED0;
    end
    else begin
        case (state)
            S_LED0:begin
                if (cnt == TIME) begin
                    state <= S_LED1;//切换到 下一个状态
                    led <=LED1;
                end
                else begin
                    state <= S_LED0;//保持原有状态
                    led <=LED0;
                end
            end 
            S_LED1:begin
                if (cnt == TIME) begin
                    state <= S_LED2;//切换到 下一个状态
                    led <=LED2;
                end
                else begin
                    state <= S_LED1;//保持原有状态
                    led <=LED1;
                end
            end
            S_LED2:begin
                if (cnt == TIME) begin
                    state <= S_LED3;//切换到 下一个状态
                    led <=LED3;
                end
                else begin
                    state <= S_LED2;//保持原有状态
                    led <=LED2;
                end
            end

            S_LED3:begin
                if (cnt == TIME) begin
                    state <= S_LED0;//切换到 下一个状态
                    led <= LED0;
                end
                else begin
                    state <= S_LED3;//保持原有状态
                    led <= LED3;
                end
            end
            default: ;
        endcase
    end
end


endmodule

跑马灯:

module horse_led(
    input clk,
    input rst_n,

    output [3:0] led
);

parameter TIME = 24'd9_999_999;//一个状态持续时间

reg [23:0] cnt;

reg [7:0] led_reg;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt = 24'd0;
    end
    else if(cnt == TIME)begin
        cnt <=24'd0;
    end
    else begin
        cnt <= cnt + 1'd1;
    end    
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        led_reg <= 8'b1111_0000;//跑马灯 从全灭到全亮再逐渐全灭,实质就是这八位的循环变化
    end
    else if(cnt == TIME)begin
        led_reg <={led_reg[0],led_reg[7:1]};
    end
    else begin
        led_reg <= led_reg;
    end
end

assign led = led_reg[3:0];

endmodule

呼吸灯:(时间分层实现(非电平分级))

module breath_led(
    input clk,
    input rst_n,

    output reg led

);

parameter cnt_us = 6'd50;
parameter cnt_ms = 10'd1000;
parameter  cnt_s=10'd1000 ;

reg [5:0] cnt1;
wire add_cnt1;//计时开始的标志
wire end_cnt1;//计时器结束的标志

reg [9:0] cnt2;
wire add_cnt2;//计时开始的标志
wire end_cnt2;//计时器结束的标志

reg [9:0] cnt3;
wire add_cnt3;//计时开始的标志
wire end_cnt3;//计时器结束的标志

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt1 <= 6'd0;

    end
    else if (add_cnt1) begin
        if (end_cnt1) begin
            cnt1 <= 6'd0;
        end
    
    else begin
        cnt1 <= cnt1+1'd1;
    end
    end
    else begin
        cnt1 <= cnt1;
    end
    
    
end
assign add_cnt1 = 1;
assign end_cnt1 = add_cnt1 && cnt1==cnt_us;





always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt2 <= 10'd0;

    end
    else if (add_cnt2) begin
        if (end_cnt2) begin
            cnt2 <= 10'd0;
        end
    
    else begin
        cnt2 <= cnt2+1'd1;
    end
    end
    else begin
        cnt2 <= cnt2;
    end
    
end

assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2 && cnt2==cnt_ms;




always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt3 <= 10'd0;

    end
    else if (add_cnt3) begin
        if (end_cnt3) begin
            cnt3 <= 10'd0;
        end
    
    else begin
        cnt3 <= cnt3+1'd1;
    end
    end
    else begin
        cnt3 <= cnt3;
    end
end
assign add_cnt3 = end_cnt2;
assign end_cnt3 = add_cnt3 && cnt3==cnt_s;


reg [1:0] flag;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        flag <= 1'd0;
    end
else if(end_cnt3)begin
    flag = ~flag;
end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        led <= 1'd0;
    end
    else if (!flag) begin
        led <= cnt3>cnt2?1'b1:1'b0;
    end
    else if(flag) begin
        led <= cnt3>cnt2?1'b0:1'b1;
    end
    else
        led <= led;

end




endmodule

流水灯式呼吸灯

module breath_led(
    input clk,
    input rst_n,

    output reg [3:0]led
);

parameter 	TIME = 100_000_000;//间隔2s
//状态空间
parameter 	S_LED0 = 2'd0;
parameter 	S_LED1 = 2'd1;
parameter 	S_LED2 = 2'd2;
parameter 	S_LED3 = 2'd3;

//三个计时器的计时上限
parameter time_us = 50;
parameter time_ms = 1000;
parameter time_s  = 1000;

reg [5:0] cnt_us;
wire add_cnt_us;//开始计时的标志
wire end_cnt_us;//结束计时的标志

reg [9:0] cnt_ms;
wire add_cnt_ms;//开始计时的标志
wire end_cnt_ms;//结束计时的标志

reg [9:0] cnt_s;
wire add_cnt_s;//开始计时的标志
wire end_cnt_s;//结束计时的标志

reg flag;//亮灭切换标志
reg [3:0] led_reg;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_us <= 6'd0;
    end
    else if(add_cnt_us)begin
        if(end_cnt_us)begin
            cnt_us <= 6'd0;
        end
        else begin
            cnt_us <= cnt_us + 1'd1;
        end
    end
    else begin
        cnt_us <= cnt_us;
    end
end

assign add_cnt_us = 1;
assign end_cnt_us = add_cnt_us && cnt_us == time_us - 1'd1;


always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_ms <= 10'd0;
    end
    else if(add_cnt_ms)begin
        if(end_cnt_ms)begin
            cnt_ms <= 10'd0;
        end
        else begin
            cnt_ms <= cnt_ms + 1'd1;
        end
    end
    else begin
        cnt_ms <= cnt_ms;
    end
end

assign add_cnt_ms = end_cnt_us;
assign end_cnt_ms = add_cnt_ms && cnt_ms == time_ms - 1'd1;


always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_s <= 10'd0;
    end
    else if(add_cnt_s)begin
        if(end_cnt_s)begin
            cnt_s <= 10'd0;
        end
        else begin
            cnt_s <= cnt_s + 1'd1;
        end
    end
    else begin
        cnt_s <= cnt_s;
    end
end

assign add_cnt_s = end_cnt_ms;
assign end_cnt_s = add_cnt_s && cnt_s == time_s - 1'd1;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        flag <= 1'b0;
    end 
    else if(end_cnt_s)begin//计满一秒,led完成了从灭→亮的变化 
        flag <= ~flag;
    end 
    else begin 
        flag <= flag;
    end 
end


reg [26:0]	cnt;//时钟计数器
reg [1:0]	current_stat;//当前状态寄存器

//计时模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//复位
		cnt <= 27'd0;//计数器清0
	end 
	else if(cnt == TIME - 1)begin//记满1s
		cnt <= 27'd0;//计数器清0
	end 
	else begin
		cnt <= cnt + 27'd1;//其他时间加1
	end 
end 

//状态切换
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		current_stat <= 2'd0;//当前状态初始化为0
	end 
	else begin
		case(current_stat)
		S_LED0:	begin//状态为0时
                    if(cnt == TIME - 1)begin
                        current_stat <= S_LED1;
                        led[0] <= 1'b0;
                    end
                    else begin
                        current_stat <= S_LED0;
                        if(!flag)begin 
                            led[0] <= (cnt_ms<cnt_s)?1'b0:1'b1;
                        end
                        else begin
                            led[0] <= (cnt_ms>cnt_s)?1'b0:1'b1;
                        end
                    end
                end 
		S_LED1:	begin
					if(cnt == TIME - 1)begin
                        current_stat <= S_LED2;
                        led[1] <= 1'b0;
                    end
                    else begin
                        current_stat <= S_LED1;
						if(!flag)begin 
                            led[1] <= (cnt_ms<cnt_s)?1'b0:1'b1;
                        end
                        else begin
                            led[1] <= (cnt_ms>cnt_s)?1'b0:1'b1;
                        end
                    end 
                end 
		S_LED2:	begin
					if(cnt == TIME - 1)begin
                        current_stat <= S_LED3;
                        led[2] <= 1'b0;
                    end
                    else begin
                        current_stat <= S_LED2;
						if(!flag)begin 
                            led[2] <= (cnt_ms<cnt_s)?1'b0:1'b1;
                        end
                        else begin
                            led[2] <= (cnt_ms>cnt_s)?1'b0:1'b1;
                        end
                    end
				end 
		S_LED3:	begin
                    if(cnt == TIME - 1)begin
                        current_stat <= S_LED0;
                        led[3] <= 1'b0;
                    end
                    else begin
                        current_stat <= S_LED3;
						if(!flag)begin 
                            led[3] <= (cnt_ms<cnt_s)?1'b0:1'b1;
                        end
                        else begin
                            led[3] <= (cnt_ms>cnt_s)?1'b0:1'b1;
                        end
                    end
                end 
		default:;
		endcase 
	end 
end 


endmodule

注:本次及以后采用的芯片型号均为:EP4CE6F17C8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值