解题思路

经典三段式,没啥花里胡哨的。 但需要注意几个细节:

①中间段采用的组合逻辑实现,可以有一些冗余状态,如ONE_HALF、TWO、TWO_HALF、THREE这些,是为了输出的时候书写方便。当然简化为只有3个状态(IDLE、HALF、ONE)也是完全可以的,只是输出要麻烦一点,可以参考我的另一篇类似题目的题解(#自动售卖机#),采用了状态简化。

②这种有冗余状态的三段式的第三段输出,状态判断需要用next_state,而不是state。

代码实现

`timescale 1ns/1ns
module seller1(
	input  wire        clk  ,
	input  wire        rst  ,
	input  wire        d1   ,
	input  wire        d2   ,
	input  wire        d3   ,
	
	output reg         out1 ,
    output reg  [1:0]  out2
);

    reg [2:0] state, next_state;
    parameter IDLE      = 3'd0;
    parameter HALF      = 3'd1;
    parameter ONE       = 3'd2;
    parameter ONE_HALF  = 3'd3;
    parameter TWO       = 3'd4;
    parameter TWO_HALF  = 3'd5;
    parameter THREE     = 3'd6;
    
    //第一段:状态跳转
    always@(posedge clk or negedge rst) begin
        if(!rst)
            state <= IDLE;
        else
            state <= next_state;
    end
    
    //第二段:状态转移(与输入的关系)
    always@(*) begin
        case(state)
            IDLE : next_state = d1 ? HALF     :(d2 ? ONE      : (d3? TWO      : next_state));
            HALF : next_state = d1 ? ONE      :(d2 ? ONE_HALF : (d3? TWO_HALF : next_state));
            ONE  : next_state = d1 ? ONE_HALF :(d2 ? TWO      : (d3? THREE    : next_state));
            ONE_HALF ,
            TWO      , 
            TWO_HALF , 
            THREE    : next_state = IDLE;
            default  : next_state = IDLE;
        endcase
    end
    
    //第三段:输出(out1)
    always@(posedge clk or negedge rst) begin
        if(!rst)
            out1 <= 1'b0;
        else if((next_state == ONE_HALF)||(next_state == TWO)||(next_state == TWO_HALF)||(next_state == THREE))
            out1 <= 1'b1;
        else
            out1 <= 1'b0;
    end
    
    //第三段:输出(out2)
    always@(posedge clk or negedge rst) begin
        if(!rst)
            out2 <= 2'd0;
        else if(next_state == TWO)
            out2 <= 2'd1;
        else if(next_state == TWO_HALF)
            out2 <= 2'd2;
        else if(next_state == THREE)
            out2 <= 2'd3;
        else
            out2 <= 2'd0;
    end
    
endmodule