水库水位控制问题-HDLbits

原题描述的比较绕,大概就是水库供水,有3个水位探测器分别为s1,s2,s3,当水位最低时,小于S1,3个进水的阀门FR1,FR2,FR3和补充阀门deltaFR都打开,当水位在S1~S3分两部分,S1~S2 开FR1和FR2,S2~S3,开FR1,这两种情况里,如果水位监测到下降,deltaFR也要打开,水位超过S3时,关闭所有阀门。

常规思路,总结描述有4个状态,代表不同水位。通过水位监测器的值,判断状态转移。输出由状态决定,deltaFR稍微特殊,需要在2个状态里分别做判断水位是否下降。

代码如下:

module top_module (
input clk,
input reset,
input [3:1] s,
output reg fr3,
output reg fr2,
output reg fr1,
output dfr
);
parameter S1_low=4'b0001,S1_S2=4'b0010,S2_S3=4'b0100,S3_more=4'b1000;
reg [3:0]state,next_state;
always @(*)
begin
case(state)
S1_low:if(s==3'b001)
next_state=S1_S2;
else
next_state=S1_low;
S1_S2:if(s==3'b011)
next_state=S2_S3;
else if(s==3'b001)
next_state=S1_S2;
else
next_state=S1_low;
S2_S3:if(s==3'b111)
next_state=S3_more;
else if(s==3'b001)
next_state=S1_S2;
else
next_state=S2_S3;
S3_more:if(s==3'b111)
next_state=S3_more;
else
next_state=S2_S3;
endcase
end

always @(posedge clk)
if(reset)
state<=S1_low;
else
state<=next_state;

reg pre_big;
always @(posedge clk)
if(reset || state<next_state)
pre_big<=1'b0;
else if(state>next_state)
pre_big<=1'b1;
assign dfr=(state==S1_low)||(pre_big);


always @(*)
begin
case(state)
S1_low:{fr3,fr2,fr1}=3'b111;
S1_S2:{fr3,fr2,fr1}=3'b011;
S2_S3:{fr3,fr2,fr1}=3'b001;
S3_more:{fr3,fr2,fr1}=3'b000;
default:{fr3,fr2,fr1}=3'b111;
endcase
end
endmodule

官方参考代码,细分了6个状态,把2种水位下降的情况也单独列为一种状态。

module top_module (
input clk,
input reset,
input [3:1] s,
output reg fr3,
output reg fr2,
output reg fr1,
output reg dfr
);


// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
// It doesn't really matter what assignment is used, as long as they're unique.
// We have 6 states here.
parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5;
reg [2:0] state, next; // Make sure these are big enough to hold the state encodings.


// Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset.
always @(posedge clk) begin
if (reset) state <= A2;
else state <= next;
end

 

// Combinational always block for state transition logic. Given the current state and inputs,
// what should be next state be?
// Combinational always block: Use blocking assignments.
always@(*) begin
case (state)
A2: next = s[1] ? B1 : A2;
B1: next = s[2] ? C1 : (s[1] ? B1 : A2);
B2: next = s[2] ? C1 : (s[1] ? B2 : A2);
C1: next = s[3] ? D1 : (s[2] ? C1 : B2);
C2: next = s[3] ? D1 : (s[2] ? C2 : B2);
D1: next = s[3] ? D1 : C2;
default: next = 'x;
endcase
end



// Combinational output logic. In this problem, a procedural block (combinational always block)
// is more convenient. Be careful not to create a latch.
always@(*) begin
case (state)
A2: {fr3, fr2, fr1, dfr} = 4'b1111;
B1: {fr3, fr2, fr1, dfr} = 4'b0110;
B2: {fr3, fr2, fr1, dfr} = 4'b0111;
C1: {fr3, fr2, fr1, dfr} = 4'b0010;
C2: {fr3, fr2, fr1, dfr} = 4'b0011;
D1: {fr3, fr2, fr1, dfr} = 4'b0000;
default: {fr3, fr2, fr1, dfr} = 'x;
endcase
end

endmodule

posted on 2025-12-12 16:19  yf.x  阅读(1)  评论(0)    收藏  举报

导航