版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
习题6-1使用状态机设计一个按键防抖电路,消除机械按键的抖动干扰(状态包括“空闲”、“抖动检测”、“稳定按下”、“稳定松开”)。按键按下时输出高电平,松开时输出低电平。抖动时间通常为10-20ms,要求状态机能够滤除抖动信号,输出稳定的按键状态。参考答案:moduledebounce(inputclk,//系统时钟,50MHzinputrst_n,//异步复位,低电平有效inputkey_in,//机械按键输入(异步信号)outputregkey_out//防抖后的稳定按键输出:按下高,松开低);//计算:50MHz=50,000,000Hz,周期T=1/50e6=20ns,20ms=20,000,000ns//计数次数=20,000,000/20=1,000,000,即需要计满1,000,000个时钟周期localparamCNT_20MS=20'd1_000_000;//参数定义:50MHz时钟下,20ms对应的计数周期数//状态定义(用3位寄存器,4个状态,预留冗余)localparamIDLE=3'd0;//空闲状态:等待按键动作localparamPRESS_CHECK=3'd1;//按下抖动检测:确认按下信号是否持续稳定localparamPRESS_STABLE=3'd2;//稳定按下:防抖完成,确认按键有效按下localparamRELEASE_CHECK=3'd3;//释放抖动检测:确认松开信号是否持续稳定//内部信号声明reg[2:0]current_state,next_state;//状态寄存器(3位,覆盖4个状态,避免非法编码遗漏)reg[19:0]cnt;//20ms计数器,位宽20位(支持最大1,048,575,满足1,000,000)regkey_sync1,key_sync2;//输入同步寄存器,两级同步消除亚稳态wirekey;//同步后的按键信号,消除异步抖动//同步输入:消除异步按键的亚稳态(两级D触发器同步)always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginkey_sync1<=1'b1;//初始默认按键松开key_sync2<=1'b1;endelsebeginkey_sync1<=key_in;key_sync2<=key_sync1;endendassignkey=key_sync2;//同步后的稳定按键信号,供状态机使用//状态寄存器:时序逻辑,时钟上升沿更新状态always@(posedgeclkornegedgerst_n)beginif(!rst_n)current_state<=IDLE;//复位后回到空闲状态elsecurrent_state<=next_state;end//计数器逻辑:仅在抖动检测状态下,且按键信号持续有效时计数always@(posedgeclkornegedgerst_n)beginif(!rst_n)begincnt<=20'd0;endelsebegin//PRESS_CHECK状态:检测按下,需要按键持续为低(按下)才计数if(current_state==PRESS_CHECK&&!key)begincnt<=cnt+1'b1;end//RELEASE_CHECK状态:检测松开,需要按键持续为高(松开)才计数elseif(current_state==RELEASE_CHECK&&key)begincnt<=cnt+1'b1;end//其他状态(空闲、稳定按下):计数器清零,等待下一次触发elsebegincnt<=20'd0;endendend//============================================================//状态转移逻辑:组合逻辑,根据当前状态和输入计算下一状态always@(*)beginnext_state=current_state;//默认状态不变,避免出现锁存器case(current_state)//空闲状态:等待按键动作IDLE:beginif(!key)//检测到按键按下(同步后信号为低)next_state=PRESS_CHECK;//进入按下抖动检测//否则保持空闲状态 end//按下抖动检测状态:确认20ms内按键持续按下PRESS_CHECK:beginif(cnt==CNT_20MS-1)begin//计数器计满20msif(!key)begin//20ms后按键仍为低(确认稳定按下)next_state=PRESS_STABLE;end//进入稳定按下状态elsebegin//20ms内按键变为高(抖动,松开了)next_state=IDLE;end//回到空闲,重新开始检测 end//计数未满时,保持当前状态(继续计数检测) end//稳定按下状态:等待按键松开PRESS_STABLE:beginif(key)//检测到按键松开(同步后信号为高)next_state=RELEASE_CHECK;//进入释放抖动检测//否则保持稳定按下状态(按键持续按下) end//释放抖动检测状态:确认20ms内按键持续松开RELEASE_CHECK:beginif(cnt==CNT_20MS-1)begin//计数器计满20msif(key)//20ms后按键仍为高(确认稳定松开)next_state=IDLE;//回到空闲状态,等待下一次按下else//20ms内按键变为低(抖动,又按下了)next_state=PRESS_CHECK;//回到按下抖动检测,重新检测按下//计数未满时,保持当前状态(继续计数检测) end//非法状态保护:任何未定义的状态都回到空闲状态default:next_state=IDLE;endcaseend//============================================================//输出逻辑:时序逻辑,根据当前状态输出稳定的按键信号//核心:仅稳定按下时输出高,其他状态输出低,覆盖所有状态,消除锁存器always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginkey_out<=1'b0;//复位时默认输出松开(低电平)endelsebegincase(current_state)PRESS_STABLE://稳定按下,输出高电平key_out<=1'b1;//其他所有状态(空闲、按下抖动检测、释放抖动检测):输出低电平default:key_out<=1'b0;endcaseendendendmodule习题6-2使用状态机设计一个简易自动售货机控制系统,支持投币、选择商品和找零功能。假设商品价格为2元,仅支持1元硬币投币。每次交易仅购买一件商品。(售货机状态包括“待机”、“投币中”、“选择商品”、“出货”、“找零”。)参考答案:这个售货机实现的核心逻辑是:投币之前是“待机”状态。逐次投入1元硬币,收到1元进入“投币中”状态,再继续投入硬币则进入“选择商品”状态。假设售货机里有四种商品(四个按键),按下任意一个表示购买1件该商品(只能买1件,无需数量选择)。然后进入“出货找零”状态。程序如下:moduleVending_machine(inputclk,//系统时钟信号inputrst_n,//异步复位信号,低电平有效inputcoin,//投币信号,高电平有效(假设为1元硬币)input[3:0]sel_goods,//商品选择信号(独热码,表示选中的商品)outputregsell,//出货信号,高电平有效(持续一个时钟周期)outputreg[3:0]change,//找零金额输出,单位元output[3:0]cnt_coin//当前累计投币金额,用于调试或显示);//状态机状态定义localparamIDLE=3'b000;//待机状态:等待用户投币localparamCOIN_INSERT=3'b001;//投币状态:正在接收用户投币localparamSELECT=3'b010;//选择状态:等待用户选择商品localparamDISPENSE=3'b011;//出货状态:送出商品localparamGIVE_CHANGE=3'b100;//找零状态:计算并输出找零金额//内部信号声明reg[2:0]current_state,next_state;//当前状态和下一状态寄存器reg[3:0]coin_count;//当前累计投币金额(单位:元)//组合逻辑:输入信号有效性检测,判断sel_goods是否为有效的独热码(有且仅有一位为高)wiresel_valid=(sel_goods!=4'b0)&&((sel_goods&(sel_goods-1))==4'b0);//时序逻辑:状态寄存器,在时钟上升沿更新当前状态,异步复位时回到初始状态IDLEalways@(posedgeclkornegedgerst_n)beginif(!rst_n)current_state<=IDLE;elsecurrent_state<=next_state;end//时序逻辑:投币金额计数器。管理金额的累加、清零。always@(posedgeclkornegedgerst_n)beginif(!rst_n)begincoin_count<=4'd0;endelsebegin//优先判断:在完成找零后,将金额清零,为下一次交易做准备if(current_state==GIVE_CHANGE)coin_count<=4'd0;//其次判断:在允许投币的状态下,接收到投币信号则金额加1elseif(coin&&(current_state==COIN_INSERT||current_state==SELECT))coin_count<=coin_count+4'd1;//其他情况保持当前金额不变endend//组合逻辑:状态转移逻辑。根据当前状态和输入信号,计算下一个状态always@(*)beginnext_state=current_state;//默认状态不变case(current_state)//1.待机状态:收到投币信号,跳转至投币状态IDLE:beginif(coin)next_state=COIN_INSERT;end//2.投币状态:仅在收到投币信号时进行判断COIN_INSERT:beginif(coin)begin//逻辑核心:判断本次投币后,总金额是否达到2元(商品价格)//coin_count是当前金额,加1后才是本次投币后的金额if(coin_count+1>=4'd2)next_state=SELECT;//金额足够,进入商品选择状态elsenext_state=COIN_INSERT;//金额不足,继续保持投币状态endend//3.选择状态:允许用户继续投币,或在金额足够时,通过有效选品进入出货状态SELECT:begin//条件:金额已达到商品价格(2元)且用户选择了有效商品if(sel_valid&&coin_count>=4'd2)next_state=DISPENSE;//满足出货条件,跳转至出货状态//若未满足出货条件,即使收到投币信号,状态也不改变//(金额累加由上面的时序逻辑独立处理,保证状态机职责单一)end//4.出货状态:完成出货动作,固定跳转至找零状态DISPENSE:next_state=GIVE_CHANGE;//5.找零状态:完成找零计算,固定返回待机状态,准备下一次交易GIVE_CHANGE:next_state=IDLE;//默认情况:为保证状态机鲁棒性,任何未知状态都返回待机状态default:next_state=IDLE;endcaseend//时序逻辑:输出信号生成。根据当前状态,在对应状态产生特定的输出信号(sell和change)always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginsell<=1'b0;change<=4'd0;endelsebegin//每个时钟周期,先将输出信号复位为默认值sell<=1'b0;change<=4'd0;case(current_state)//在出货状态,产生一个持续一个时钟周期的出货脉冲DISPENSE:sell<=1'b1;//在找零状态,计算并输出找零金额//此处使用的coin_count是清零前的值,代表本次交易的总投币额GIVE_CHANGE:begin//只有当投币金额大于等于商品价格时才需要找零if(coin_count>=4'd2)change<=coin_count-4'd2;endendcaseendend//输出:当前投币金额,将内部寄存器coin_count直接输出,供外部显示或调试使用assigncnt_coin=coin_count;endmodule习题6-3设计一个UART串口接收机,支持8位数据、1位停止位、无校验位的串口协议,波特率为9600bps。使用状态机实现,系统状态包括“空闲”、“起始位检测”、“数据位接收”、“停止位检测”。参考答案:串口设备包含发送和接收功能,接收电路将8位串行输入的数据转变成并行数据输出。在波特率为9600bps的情况下每个比特传输所需时长为104.1667μs,系统50MHz时钟周期为20ns,因此,每传输1个比特数据需要5208个系统时钟。程序中用计数器计数5208(从0到5207)的方式实现9600波特率(波特率因子16)对应的逻辑分频。moduleuart_rx(inputclk,inputrst_n,inputrx,outputreg[7:0]rx_data,outputregrx_done);localparamCLK_FREQ=50_000_000;localparamBAUD_RATE=9600;localparamBAUD_DIV=CLK_FREQ/BAUD_RATE;//5208localparamBAUD_MID=BAUD_DIV/2;//2604localparamIDLE=2'b00;localparamSTART_BIT=2'b01;localparamDATA_BITS=2'b10;localparamSTOP_BIT=2'b11;reg[1:0]state,next_state;reg[12:0]baud_cnt;reg[2:0]bit_cnt;reg[7:0]shift_reg;reg[1:0]rx_sync;//输入同步always@(posedgeclkornegedgerst_n)beginif(!rst_n)rx_sync<=2'b11;elserx_sync<={rx_sync[0],rx};end//状态寄存器always@(posedgeclkornegedgerst_n)beginif(!rst_n)state<=IDLE;elsestate<=next_state;end//状态转移always@(*)beginnext_state=state;case(state)IDLE:beginif(rx_sync==2'b00)next_state=START_BIT;endSTART_BIT:beginif(baud_cnt==BAUD_MID)beginif(rx_sync[0]==1'b0)next_state=DATA_BITS;elsenext_state=IDLE;endendDATA_BITS:beginif(bit_cnt==3'd7&&baud_cnt==BAUD_DIV-1)next_state=STOP_BIT;endSTOP_BIT:beginif(baud_cnt==BAUD_MID)next_state=IDLE;endendcaseendalways@(posedgeclkornegedgerst_n)beginif(!rst_n)beginbaud_cnt<=13'd0;bit_cnt<=3'd0;shift_reg<=8'd0;rx_data<=8'd0;rx_done<=1'b0;endelsebeginrx_done<=1'b0;case(state)IDLE:beginbaud_cnt<=13'd0;bit_cnt<=3'd0;endSTART_BIT:beginif(baud_cnt==BAUD_MID)baud_cnt<=13'd0;elsebaud_cnt<=baud_cnt+13'd1;endDATA_BITS:begin//数据采样if(baud_cnt==BAUD_MID)shift_reg<={rx_sync[0],shift_reg[7:1]};//比特结束if(baud_cnt==BAUD_DIV-1)beginbaud_cnt<=13'd0;bit_cnt<=bit_cnt+1'b1;endelsebaud_cnt<=baud_cnt+13'd1;endSTOP_BIT:beginif(baud_cnt==BAUD_MID)beginif(rx_sync[0]==1'b1)beginrx_data<=shift_reg;rx_done<=1'b1;endbaud_cnt<=13'd0;endelsebaud_cnt<=baud_cnt+13'd1;enddefault:baud_cnt<=13'd0;endcaseendendendmodule习题6-4使用状态机设计一个简易电梯控制系统,支持3层楼的请求响应和方向优先级判断。电梯初始位置为1楼。假设电梯每次移动一层,开门时间为2秒。(系统状态包括“空闲”、“上行”、“下行”、“开门”、“关门”)参考答案: 电梯运行规则是:有运行方向时,优先响应同方向请求;无同方向请求时,再响应反方向请求;无请求时回到空闲状态。复位后电梯状态也是“空闲”,位于1楼。开门时间为2秒,在假设系统时钟为1Hz的前提下,程序如下:moduleelevator_3floor(inputclk,//1Hz系统时钟(开门2秒=2个时钟周期)inputrst_n,//异步复位,低电平有效input[2:0]call,//call[0]=1楼呼叫,call[1]=2楼呼叫,call[2]=3楼呼叫(独热/组合编码)output[1:0]floor,//楼层编码:00=1楼,01=2楼,10=3楼outputup,//上行指示:1=电梯上行outputdown,//下行指示:1=电梯下行outputopen//开门指示:1=电梯门打开);//状态与参数定义localparamIDLE=3'd0;//空闲:无请求时待命localparamUP=3'd1;//上行:响应上行请求,向上移动localparamDOWN=3'd2;//下行:响应下行请求,向下移动localparamOPEN=3'd3;//开门:到达目标楼层,开门响应localparamCLOSE=3'd4;//关门:开门完成,准备下一次运行//楼层常量(提升代码可读性)localparamFLOOR_1=2'd0;localparamFLOOR_2=2'd1;localparamFLOOR_3=2'd2;localparamOPEN_TIME=2'd2;//开门时间:2个时钟周期(1Hz时钟下对应2秒)//内部信号声明reg[2:0]state,next_state;//状态寄存器:当前状态/组合逻辑计算的下一状态reg[1:0]floor_reg;//楼层寄存器(时序逻辑,同步更新楼层)reg[1:0]open_cnt;//开门计时器:仅在OPEN状态计数,记录开门时长reg[2:0]pending_call;//待处理呼叫寄存器:跟踪未响应的呼叫请求//组合逻辑输出assignup=(state==UP);//状态为上行时,输出上行指示assigndown=(state==DOWN);//状态为下行时,输出下行指示assignopen=(state==OPEN);//状态为开门时,输出开门指示assignfloor=floor_reg;//楼层输出直接映射时序寄存器//组合逻辑辅助信号//当前楼层是否有待处理呼叫(需要开门响应)wirehas_call_here=(floor_reg==FLOOR_1&&pending_call[0])||(floor_reg==FLOOR_2&&pending_call[1])||(floor_reg==FLOOR_3&&pending_call[2]);//当前楼层是否存在上行请求(更高楼层有待处理呼叫)wirehas_up_request=(floor_reg==FLOOR_1&&(pending_call[1]||pending_call[2]))||(floor_reg==FLOOR_2&&pending_call[2]);//当前楼层是否存在下行请求(更低楼层有待处理呼叫)wirehas_down_request=(floor_reg==FLOOR_3&&(pending_call[1]||pending_call[0]))||(floor_reg==FLOOR_2&&pending_call[0]);//组合逻辑:状态转移决策(基于当前状态、请求、楼层计算下一状态)always@(*)beginnext_state=state;//默认状态不变,避免Verilog推断锁存器case(state)//----------空闲状态:等待请求,按优先级响应----------IDLE:beginif(pending_call!=3'b000)begin//有待处理请求if(has_up_request)//优先级1:存在上行请求,启动上行next_state=UP;elseif(has_down_request)//优先级2:存在下行请求,启动下行next_state=DOWN;elseif(has_call_here)//优先级3:当前楼层有呼叫,直接开门next_state=OPEN;//无有效请求时保持空闲endend//----------上行状态:逐层上行,到达目标楼层停车----------UP:beginif(has_call_here)begin//到达目标楼层,开门响应next_state=OPEN;endelseif(floor_reg==FLOOR_3)begin//到达顶层,检查反方向请求if(has_down_request)//有下行请求,切换下行next_state=DOWN;else//无请求,回到空闲next_state=IDLE;endelsebegin//未到顶层且无目标楼层,继续上行next_state=UP;endend//----------下行状态:逐层下行,到达目标楼层停车----------DOWN:beginif(has_call_here)begin//到达目标楼层,开门响应next_state=OPEN;endelseif(floor_reg==FLOOR_1)begin//到达底层,检查反方向请求if(has_up_request)//有上行请求,切换上行next_state=UP;else//无请求,回到空闲next_state=IDLE;endelsebegin//未到底层且无目标楼层,继续下行next_state=DOWN;endend//----------开门状态:计时2秒,结束后关门----------OPEN:beginif(open_cnt==OPEN_TIME-1)//开门时长满足2秒,进入关门next_state=CLOSE;elsenext_state=OPEN;//未到时间,保持开门end//----------关门状态:检查剩余请求,快速响应----------CLOSE:beginif(pending_call!=3'b000)begin//有剩余请求,直接跳转到对应状态if(has_up_request)next_state=UP;elseif(has_down_request)next_state=DOWN;elseif(has_call_here)next_state=OPEN;elsenext_state=IDLE;endelsebegin//无剩余请求,回到空闲next_state=IDLE;endend//异常状态保护:任何未定义状态强制回到空闲default:next_state=IDLE;endcaseend//时序逻辑:状态寄存器always@(posedgeclkornegedgerst_n)beginif(!rst_n)state<=IDLE;//异步复位后,强制回到空闲状态elsestate<=next_state;//时钟上升沿更新为下一状态end//时序逻辑:待处理呼叫管理always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginpending_call<=3'b000;//复位后无待处理请求endelsebegin//开门时清除当前楼层的请求(已响应,避免重复触发)if(state==OPEN)begincase(floor_reg)FLOOR_1:pending_call[0]<=1'b0;FLOOR_2:pending_call[1]<=1'b0;FLOOR_3:pending_call[2]<=1'b0;default:pending_call<=3'b000;//异常保护endcaseend//持续记录新呼叫(阻塞赋值确保清除和新增同步生效)pending_call<=pending_call|call;endend//时序逻辑:楼层移动+开门计时器always@(posedgeclkornegedgerst_n)beginif(!rst_n)begin//复位初始化:1楼、开门计时器清零floor_reg<=FLOOR_1;open_cnt<=2'd0;endelsebegin//--------------开门计时器:仅在OPEN状态计时,退出自动停止--------------if(state==OPEN)open_cnt<=open_cnt+1'b1;//进入开门状态,计时递增elseopen_cnt<=2'd0;//非开门状态,计时器清零(无需额外判断,直接复位)//--------------楼层移动:基于当前状态直接驱动,无跨周期依赖--------------//上行:当前状态为UP,且未到顶层,每周期移动1层if(state==UP&&floor_reg!=FLOOR_3)floor_reg<=floor_reg+1'b1;//下行:当前状态为DOWN,且未到底层,每周期移动1层elseif(state==DOWN&&floor_reg!=FLOOR_1)floor_reg<=floor_reg-1'b1;//其他状态(空闲、开门、关门):楼层保持不变elsefloor_reg<=floor_reg;endendendmodule习题6-5使用状态机模拟一个温控风扇系统,根据温度传感器数据调整风扇转速。温度范围为0-100℃,风扇转速分为4档(0%、33%、66%、100%),由PWM信号控制。(系统状态包括“温度采样”、“转速调整”、“PWM生成”)参考答案:温控风扇系统的运行逻辑:系统持续对温度传感器数据进行采样,根据采样温度严格匹配对应转速档位(温度0-24℃时,风扇为0%静止;25-49℃时,转速33%;50-74℃时,转速66%;≥75℃时,转速100%);完成转速档位调整后,同步输出对应占空比的PWM信号驱动风扇,PWM周期固定为1kHz(开门时间同为2秒,在假设系统时钟为50MHz的前提下,PWM周期对应50000个时钟周期);无温度变化时维持当前转速输出,确保风扇稳定运行;复位后风扇状态初始化为“空闲”,输出0%转速的PWM信号,位于0档待命。程序如下:moduletemp_ctrl_fan(inputclk,inputrst_n,input[7:0]temp,//修正:温度范围0-100℃→8位足够outputregpwm_out);//参数定义localparamCLK_FREQ=50_000_000;//50MHz系统时钟localparamPWM_FREQ=1_000;//1kHzPWM频率localparamPWM_PERIOD=CLK_FREQ/PWM_FREQ;//50000个时钟周期//状态定义(闭环循环:采样→调整→生成PWM→采样)localparamSAMPLE=2'd0;localparamADJUST=2'd1;localparamGEN_PWM=2'd2;//内部信号声明reg[1:0]state,next_state;reg[1:0]speed_level;reg[15:0]pwm_cnt;//计数器(覆盖50000)reg[15:0]pwm_duty;reg[7:0]temp_sample;//温度采样寄存器//组合逻辑:状态转移always@(*)beginnext_state=state;case(state)SAMPLE:next_state=ADJUST;//采样完成→调整转速ADJUST:next_state=GEN_PWM;//调整完成→生成PWMGEN_PWM:next_state=SAMPLE;//修复:PWM生成后→回到采样(循环核心)default:next_state=SAMPLE;//异常保护endcaseend//时序逻辑:状态寄存器always@(posedgeclkornegedgerst_n)beginif(!rst_n)state<=SAMPLE;elsestate<=next_state;end//时序逻辑:温度采样(仅在SAMPLE状态锁存温度)always@(posedgeclkornegedgerst_n)beginif(!rst_n)temp_sample<=8'd0;elseif(state==SAMPLE)//仅在采样状态更新temp_sample<=temp;end//时序逻辑:转速档位调整(仅在ADJUST状态更新)always@(posedgeclkornegedgerst_n)beginif(!rst_n)speed_level<=2'd0;elseif(state==ADJUST)begin//仅在调整状态更新if(temp_sample<25)speed_level<=2'd0;//0%(0-24℃)elseif(temp_sample<50)speed_level<=2'd1;//33%(25-49℃)elseif(temp_sample<75)speed_level<=2'd2;//66%(50-74℃)elsespeed_level<=2'd3;//100%(≥75℃)endend//组合逻辑:PWM占空比计算(四舍五入提升精度)always@(*)begincase(speed_level)2'd0:pwm_duty=16'd0;//0%2'd1:pwm_duty=(PWM_PERIOD*1+1)/3;//33.33%→四舍五入2'd2:pwm_duty=(PWM_PERIOD*2+1)/3;//66.67%→四舍五入2'd3:pwm_duty=PWM_PERIOD;//100%default:pwm_duty=16'd0;endcaseend//时序逻辑:PWM周期计数器always@(posedgeclkornegedgerst_n)beginif(!rst_n)pwm_cnt<=16'd0;elseif(pwm_cnt>=PWM_PERIOD-1)//计满一个PWM周期→复位pwm_cnt<=16'd0;elsepwm_cnt<=pwm_cnt+1'd1;end//7.时序逻辑:PWM输出always@(posedgeclkornegedgerst_n)beginif(!rst_n)pwm_out<=1'b0;elsepwm_out<=(pwm_cnt<pwm_duty);//计数小于占空比→输出高电平endendmodule习题6-6设计一个简易计算器核心逻辑,支持加减乘除四则运算(如“A+B=”),每次仅支持单次运算。要求如下:-使用状态机实现,状态包括“输入A”、“输入操作符”、“输入B”、“计算结果”。-输入:数字按键(`num[3:0]`,4位二进制表示0-9)、操作符按键(`op[1:0]`,00-加,01-减,10-乘,11-除)。-输出:计算结果(`result[7:0]`,8位二进制)。参考答案:围绕简易计算器功能实现,以状态机为核心架构,明确定义四大核心要素:一是状态划分,以INPUT_A(输入A)、INPUT_OP(选操作符)、INPUT_B(输入B)、CALC(计算)四个状态精准覆盖运算全流程,构建闭环流程骨架;二是同步机制,对按键、操作符等异步输入采用打拍同步,定义边沿触发规则,规避抖动与亚稳态;三是数据边界,限定运算数输入范围、明确操作符采样条件,定义四则运算的异常防护规则;四是输出逻辑,定义结果保持与有效标志的时序关系。modulecalculator_simple(inputclk,inputrst_n,input[3:0]num,input[1:0]op,inputenter,outputreg[7:0]result,outputregvalid);//状态定义localparamINPUT_A=2'b00;localparamINPUT_OP=2'b01;localparamINPUT_B=2'b10;localparamCALC=2'b11;reg[1:0]state,next_state;reg[7:0]A,B;reg[1:0]cur_op;//同步打拍:按键同步+防抖(核心可靠性补全,仅增加1个寄存器)regenter_d1,enter_d2;wireenter_edge=enter_d1&~enter_d2;//同步后的上升沿,无抖动//操作符同步:简单2级打拍,防毛刺regop_d1,op_d2;wireop_valid=op_d1&~op_d2;//操作符有效上升沿//状态转移always@(*)beginnext_state=state;case(state)INPUT_A:if(enter_edge)next_state=INPUT_OP;INPUT_OP:if(op_valid)next_state=INPUT_B;//用同步后的边沿触发,更稳定INPUT_B:if(enter_edge)next_state=CALC;CALC:next_state=INPUT_A;endcaseend//同步寄存+核心逻辑:一个always块,补核心可靠性always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginstate<=INPUT_A;A<=8'd0;B<=8'd0;cur_op<=2'b00;enter_d1<=1'b0;enter_d2<=1'b0;op_d1<=2'b00;op_d2<=2'b00;result<=8'd0;valid<=1'b0;endelsebegin//按键同步打拍:核心防抖+同步enter_d2<=enter_d1;enter_d1<=enter;//操作符同步打拍:防毛刺,极简同步op_d2<=op_d1;op_d1<=op;//状态更新state<=next_state;//数据寄存:仅用同步后的信号触发case(state)INPUT_A:if(num<=9&&A<10)A<=A*10+num;//数字输入,边界限制INPUT_OP:if(op_valid)cur_op<=op;//操作符边沿采样,避免重复和毛刺INPUT_B:if(num<=9&&B<10)B<=B*10+num;//数字输入,边界限制CALC:begin//计算+结果保持+错误标记case(cur_op)2'b00:result<=A+B;//加法,无溢出风险(8位最大255,A+B<=198)2'b01:result<=(A>=B)?(A-B):8'd0;//减法,负数置02'b10:beginif(A*B<=255)beginresult<=A*B;valid<=1'b1;endelsebeginresult<=8'd0;valid<=1'b0;//溢出标记无效,不混肴错误endend2'b11:beginresult<=(B!=0)?(A/B):8'd0;//除法,除零置0valid<=(B!=0)?1'b1:1'b0;//除零标记无效enddefault:beginresult<=8'd0;valid<=1'b0;endendcase//计算完成后,valid保持,不立即清零,结果可查看//若需手动清零,可增加复位或外部清零信号,此处默认保持enddefault:;//其他状态不更新数据,保持极简endcaseendendendmodule习题6-7设计一个单周期CPU核心的状态机,支持取指、译码、执行等基本操作。假设CPU支持两条指令:`ADD`(加法)和`LOAD`(加载数据),指令格式:`ADD`为`0001`+操作数,`LOAD`为`0010`+地址。参考答案:一个单周期CPU核心的状态机,支持取指、译码、执行三个基本操作。CPU只支持两条指令:ADD(加法)和LOAD(加载数据)。指令宽度为8位,高4位为操作码,低4位为操作数或存储器地址。其中ADD指令的操作码为0001,执行时将低4位操作数与累加器相加,结果存入累加器并输出;LOAD指令的操作码为0010,执行时以低4位为地址,从数据存储器中读取数据,存入累加器并输出。数据存储器容量为16字节,复位时通过时序逻辑完成初始化,每个地址单元的值设为地址值的2倍,用于仿真和实际运行。程序使用三个状态:FETCH(取指)、DECODE(译码)、EXE(执行),状态之间顺序循环。所有寄存器在时钟上升沿更新,复位信号为低电平有效。最终执行结果通过result端口输出。程序代码如下:modulesingle_cycle_cpu(inputclk,//时钟:同步所有逻辑,无异步信号inputrst_n,//低电平复位:所有信号清零,确保上电确定状态input[7:0]instr,//外部输入指令:8位,符合指令格式outputreg[7:0]result//执行结果:默认输出ACC值,执行阶段更新);//状态定义localparamFETCH=2'b00;//取指:锁存外部指令localparamDECODE=2'b01;//译码:解析操作码、操作数localparamEXE=2'b10;//执行:执行ADD/LOAD,更新ACC和结果reg[1:0]state,next_state;//状态寄存器:2位,支持3状态编码reg[7:0]ir;//指令寄存器:同步锁存外部指令,防亚稳态reg[3:0]opcode;//操作码:高4位,ADD=0001,LOAD=0010reg[3:0]operand;//操作数/地址:低4位,ADD的操作数、LOAD的地址reg[7:0]acc;//累加器(核心新增):存储中间结果,实现指令联动reg[7:0]mem[0:15];//数据存储器:16字节,仅用于LOAD读操作reg[3:0]init_cnt;//初始化计数器:循环16次,覆盖所有存储单元reginit_done;//初始化完成标志:确保初始化后不再重复写入//数据存储器初始化。核心逻辑:复位后通过时钟循环给16个存储单元赋值,完成后保持数据不变always@(posedgeclkornegedgerst_n)beginif(!rst_n)begin//复位初始化:计数器清零、初始化未完成、所有存储单元赋初始值init_cnt<=4'd0;init_done<=1'b0;for(integeri=0;i<16;i=i+1)mem[i]<=i*2;//
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高一物理暑假作业《抛体运动》专题含答案
- GEO优化工具哪个好?2026年十大主流平台综合测评与选型指南
- 团建活动免责协议书
- 2024年巡操岗位职责(共8篇)
- 2024年全国公共营养师之三级营养师考试绝密预测题(详细参考解析)
- 25春沪科版初中数学七年级下册 专题113 期末复习-选择压轴题专项训练(压轴题专项训练)(沪科版)(解析版)
- TAZIIS295计轴的研究与分析
- 平顶山科技职业学院2026年单独招生《职业技能测试》模拟试题及答案解析(中职毕业生及其他考生用)
- 2026年全国临床执业医师考试第三单元点睛提分卷一
- ISO10012-2026《质量管理-测量管理体系要求》之18:“7.3意识”专业指导问答材料(雷泽佳编制-2026A0)
- 建筑工程技术专业毕业论文
- 北欧神话课件
- (正式版)XJJ 144-2022 《装配式墙板及免拆底模钢筋桁架楼承板应用技术标准 附条文说明》
- 机场安全防爆培训课件
- DB3304∕T 053-2020 有轨电车工程设计规范
- 《水的蒸发和凝结》课件
- 新生儿腹胀护理查房
- 浙江留用地管理办法
- 中老年骨病健康讲座课件
- DB 3307∕T 129-2023 设区的市地方性法规制定工作规范
- 罐式车辆运输管理制度
评论
0/150
提交评论