线性序列机原理与应用

设计方法第一课

四个小任务实现线性序列机

任务1

在这里插入图片描述
让led灯亮0.25s,灭0.75s,不再是等长时间反转

计数器有时是最大值减1,有时候只是某个值,区别在于周期性计数时,由最大值变0会占一个时钟周期

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter <= 0;
	else if(counter == maxcnt - 1)
		counter <= 0;
	else 
		counter <= counter + 1'd1;
		

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		led <= 0;
	else if(counter == 0)
		led <= 1;
	**else if(counter == maxcnt/4)** 
		led <= 0;

仿真图

在这里插入图片描述
亮灯持续时间0.25ms,可测得灭时间0.75ms,少三个数量级是因为仿真时参数重定义,减少三个0,加快仿真进度。

任务1总结

计数器不仅可以取最大值,还可以取中间的任意值。
可以将计数器当作一把时间的尺子,用计数器的每一个计数值当作一个刻度,从而得到各个需要的时刻。
在指定的时刻,执行需要的操作。

任务2

在这里插入图片描述
让led以亮0.25s 灭0.5s,亮0.75s,灭1s的规律,持续循环闪烁。
在这里插入图片描述
设计思路:顶一个0.25s的最小单位,每过0.25s的若干整数倍对led进行赋值操作

parameter maxcnt = 12_500_000;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter <= 0;
	else if(counter == maxcnt*10 - 1)
		counter <= 0;
	else 
		counter <= counter + 1'd1;
		

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		led <= 1;
	else if(counter == 0) 
		led <= 1;
	else if(counter == maxcnt)
		led <= 0;
	else if(counter == maxcnt*3) 
		led <= 1;
	else if(counter == maxcnt*6) 
		led <= 0;
	else if(counter == maxcnt*10) 
		led <= 1;

任务2仿真图

在这里插入图片描述

波形查看,右键grid,在timeunint中由ns改为ms,方便查看时间刻度

在这里插入图片描述

思路改进

可以再定义一个计数器,让counter每次计数到最大值时,新定义的counter1加1,如此,不用再给maxcnt*整数,只需在相应的counter1到时,用case语句对led赋值
在这里插入图片描述

任务三_由用户指定(第一个可以在程序运行时对led进行状态操作)

以0.25s为一个最小时间单元,以八个小段(2s)为一个循环周期,led在每一小段的状态由一个8位的输入端口指定(用八个开关,决定灯的亮灭)
新增一个input[7:0] switch;

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		led <= 1;
	else begin	
		case(counter0)
		0:led <= switch[0];
		1:led <= switch[1];
		2:led <= switch[2];
		3:led <= switch[3];
		4:led <= switch[4];
		5:led <= switch[5];
		6:led <= switch[6];
		7:led <= switch[7];
 		default:led <= led;
		endcase

在这里插入图片描述
当counter0计数到几时,led就按照8位的开关第几位状态亮灭

任务四_受控线性序列机

在第三个任务基础上,实现每隔一定的时间,执行一轮led8个状态的切换控制
在这里插入图片描述
处理方法:每隔一定的时间,时间不一定是1s。将两个状态分开处理,各使用一个计数器来实现。

  • 空闲态的间隔时间,用一个计数器实现counter2

  • 变化态的最小时间段,也就是0.25s,用一个计数器实现counter0

  • 8个状态,在用一个三位计数器来实现counter1

  • 用于控制led切换时间间隔的counter0
    计数最大值:maxcnt0 = 0.2510001000*1000/20 - 1 = 12_500_000 - 1
    计数条件:1秒时间到,也就是counter2计数满,8个状态切换还没完,也就是counter1一轮还没结束
    清零条件:技术到最大值,或者是空闲等待计数器counter2处于计数过程中

  • 用于计数当前输出led第几个状态的计数器counter1
    技术最大值:maxcnt 1= 8-1 = 7
    计数条件:0.25秒counter2计数器计满
    清零条件:计数到最大值

  • 用于空闲状态计时的计数器counter2
    计数最大值:maxcnt2 = 110001000*1000/20 -1 =50000000-1
    计数条件:led八个状态输出完成
    清零条件:计数到最大值

counter0(0.25s定时器)

  • 等待空闲时间,此时间内counter0不计数
  • 8个0.25秒时间段内,循环计数
parameter maxcnt0 = 12_500_000 - 1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
	counter0 <= 0;
else if(en_counter0)begin
	if(counter0 == maxcnt0)
		counter0 <= 0;
	else 
		counter0 <= counter + 1'd1;
		end
	else 
		counter0 <= 0;

counter1(8状态计数器)

reg[2:0]counter1;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter1 <= 0;
	else if (counter0 == maxcnt0) 
		counter1 <= counter1+1'd1;

counter2(空闲状态寄存器)

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter2 <= 0;
	else if(en_counter2)begin
		if(counter2 = maxcnt2)
			counter2 <= 0;
		else 
			counter2<=counter2+1'd1;
		end
	else
		counter2 <= 0;
		

使能信号分析

en_counter2

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		en_counter2 <= 1'd1;
	else if((counter1 == 7) &&(counter0 == maxcnt0)
		en_counter2 <= 1;
	else if (counter2 == maxcnt2)
		en_counter2 <= 0;

en_counter1和空闲状态想法

assign en_counter0 =~en_counter2
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		en_counter2 <= 1'd1;

在这里插入图片描述
led在en_counter0拉高时计数,变化规律按switch中的由低到高规律变化

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值