该文章为汇总文章Verilog学习代码总结的状态机——空调机部分。
该状态机为moore型时序电路。
采用三段式设计方式。
题目要求
设计一个空调机的控制机。温度传感器控制两个输入端temp_high和temp_low, 如果室内温度较高,则temp_high为’1’, 同时temp_low为’0’; 如果室内温度较低,则temp_high为’0’, 同时temp_ low为’1’; 如果室内温度正常,则temp_high为’0’, 同时temp_low为’0’。 根据输入端temp_high和temp_ _low的值来判断当前的状态是: 1.too_hot (太热) ; 2. too_cold (太冷) ; 3.just_right (正好),然后决定输出端heat和cool的值是’1’还是’0’,从而控制是制冷还是制热。
要求:
1.画出有限状态机,标明状态转换条件;
2.写出程序代码,标注说明和解释;
3.写出验证程序,对设计进行全面的验证。
状态转移图
源代码
module air(clk,rst,temp_high,temp_low,heat,cool);
input clk,rst,temp_high,temp_low;
output heat,cool;
reg heat,cool;
reg [1:0] cur_state,next_state;
//定义三个状态
parameter TOO_HIGH = 2'b10,
JUST_RIGHT = 2'b00,
TOO_LOW = 2'b01;
//时序 设置当前状态为预设的下一状态或初始
always @(posedge clk or posedge rst) begin
if(rst)begin
//重设置零
cur_state <= JUST_RIGHT;
next_state <= JUST_RIGHT;
end else begin
cur_state <= next_state;
end
end
//根据当前状态决定输出
always @(cur_state) begin
case (cur_state)
TOO_HIGH: begin
{heat,cool} = 2'b01;
end
JUST_RIGHT: begin
{heat,cool} = 2'b00;
end
TOO_LOW: begin
{heat,cool} = 2'b10;
end
default: begin
{heat,cool} = 2'b00;
end
endcase
end
//根据输入决定下一预设状态
always @(cur_state or temp_high or temp_low) begin
case (cur_state)
TOO_HIGH: begin
next_state = (temp_high == 1)?TOO_HIGH:JUST_RIGHT;
end
JUST_RIGHT: begin
if (temp_high == 1 && temp_low == 0) begin
next_state = TOO_HIGH;
end else if (temp_high == 0 && temp_low == 1) begin
next_state = TOO_LOW;
end else begin
next_state = JUST_RIGHT;
end
end
TOO_LOW: begin
next_state = (temp_low == 1)?TOO_LOW:JUST_RIGHT;
end
default: begin
next_state = JUST_RIGHT;
end
endcase
end
endmodule
测试代码
`timescale 1ns/1ns
module tb_air;
reg clk,rst,temp_high,temp_low;
wire heat,cool;
parameter PERIOD = 10;
parameter CHANGE_PERIOD = 4*PERIOD;
//初始化各值
initial begin
clk = 1'b0;
rst = 1'b0;
temp_high = 1'b0;
temp_low = 1'b0;
end
//设定时钟周期
initial
forever #(PERIOD/2) clk = ~clk;
//重置模块
initial begin
#PERIOD rst = 1;
#PERIOD rst = 0;
end
initial begin
//测试JUST_RIGHT状态下输入改变
#CHANGE_PERIOD {temp_high,temp_low} = 2'b11;
#CHANGE_PERIOD {temp_high,temp_low} = 2'b00;
#CHANGE_PERIOD {temp_high,temp_low} = 2'b01;
//转入TOO_LOW,测试TOO_LOW状态下输入改变
#CHANGE_PERIOD {temp_high,temp_low} = 2'b01;
#CHANGE_PERIOD {temp_high,temp_low} = 2'b11;
#CHANGE_PERIOD {temp_high,temp_low} = 2'b10;
//重新转入JUST_RIGHT
#CHANGE_PERIOD {temp_high,temp_low} = 2'b10;
//转入TOO_HIGH,测试TOO_HIGH状态下输入改变
#CHANGE_PERIOD {temp_high,temp_low} = 2'b11;
#CHANGE_PERIOD {temp_high,temp_low} = 2'b10;
#CHANGE_PERIOD {temp_high,temp_low} = 2'b00;
#CHANGE_PERIOD $finish;
end
//实例化模块
air i1(clk,rst,temp_high,temp_low,heat,cool);
endmodule //tb_air