题解 | #自动贩售机2#
Tips
这题纯粹是牛客的锅~
d1,d2,sel只维持半个时钟周期,因为是组合逻辑,所以当d1为真的时候马上等于S1,但是因为有了这句,所以后半个时钟周期又变回了S0,最后时钟来临时采到的还是S0。
本地测试不按照上述思路,波形是正确的,但是牛客就有问题。。。按照上述思路改了一下才通过。
Verilog Code
`timescale 1ns/1ns
module seller2(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire sel ,
output reg out1,
output reg out2,
output reg out3
);
//*************code***********//
//行为描述
parameter S0 = 3'd0, S1 = 3'd1, S2 = 3'd2, S3 = 3'd3, S4 = 3'd4;
reg [2:0] state_cur = S0, state_next = S0;
wire [2:0] in;
reg [2:0] temp;
assign in = {d1, d2, sel};
always @(posedge clk or negedge rst)begin
if(~rst)begin
state_cur <= S0;
end
else begin
state_cur <= state_next;
end
end
always @(posedge clk or negedge rst)begin
if(~rst)begin
{out1, out2, out3} <= 3'b000;
end
else begin
{out1, out2, out3} <= temp;
end
end
//状态切换
always @(*)begin
if(~rst)begin
state_next = S0;
end
else begin
case(state_cur)
S0:begin
if(in == 3'b100||in == 3'b101)begin
state_next = S1;
end
else if(in == 3'b010||in == 3'b011)begin
state_next = S2;
end
else if(in == 3'b000||in == 3'b001)begin
state_next = state_next;
end
end
S1:begin
if(in == 3'b100||in == 3'b101)begin
state_next = S2;
end
else if(in == 3'b010)begin
state_next = S0;
end
else if(in == 3'b011)begin
state_next = S3;
end
else if(in == 3'b000||in == 3'b001)begin
state_next = state_next;
end
end
S2:begin
if(in == 3'b100||in == 3'b010)begin
state_next = S0;
end
else if(in == 3'b101)begin
state_next = S3;
end
else if(in == 3'b011)begin
state_next = S4;
end
else if(in == 3'b000||in == 3'b001)begin
state_next = state_next;
end
end
S3:begin
if(in == 3'b101)begin
state_next = S4;
end
else if(in == 3'b011)begin
state_next = S0;
end
else if(in == 3'b000||in == 3'b001)begin
state_next = state_next;
end
end
S4:begin
if(in == 3'b101||in == 3'b011)begin
state_next = S0;
end
else if(in == 3'b000||in == 3'b001)begin
state_next = state_next;
end
end
default:begin
state_next = state_next;
end
endcase
end
end
//状态输出
always @(posedge clk or negedge rst)begin
if(~rst)begin
temp <= 3'b000;
end
else begin
case(state_cur)
S0:begin
if(in == 3'b100||in == 3'b101)begin
temp <= 3'b000;
end
else if(in == 3'b010||in == 3'b011)begin
temp <= 3'b000;
end
else if(in == 3'b000||in == 3'b001)begin
temp <= 3'b000;
end
end
S1:begin
if(in == 3'b100||in == 3'b101)begin
temp <= 3'b000;
end
else if(in == 3'b010)begin
temp <= 3'b100;
end
else if(in == 3'b011)begin
temp <= 3'b000;
end
else if(in == 3'b000||in == 3'b001)begin
temp <= 3'b000;
end
end
S2:begin
if(in == 3'b100)begin
temp <= 3'b100;
end
else if(in == 3'b010)begin
temp <= 3'b101;
end
else if(in == 3'b101)begin
temp <= 3'b000;
end
else if(in == 3'b011)begin
temp <= 3'b000;
end
else if(in == 3'b000||in == 3'b001)begin
temp <= 3'b000;
end
end
S3:begin
if(in == 3'b101)begin
temp <= 3'b000;
end
else if(in == 3'b011)begin
temp <= 3'b010;
end
else if(in == 3'b000||in == 3'b001)begin
temp <= 3'b000;
end
end
S4:begin
if(in == 3'b101)begin
temp <= 3'b010;
end
else if(in == 3'b011)begin
temp <= 3'b011;
end
else if(in == 3'b000||in == 3'b001)begin
temp <= 3'b000;
end
end
default:begin
temp <= 3'b000;
end
endcase
end
end
//*************code***********//
endmodule
Testbench Code
`timescale 1ns/1ns
module testbench();
reg clk = 1'b1, rst = 1'b0;
reg d1 = 1'b0, d2 = 1'b0, sel = 1'b0;
wire out1, out2, out3;
always #5 clk = ~clk; // Create clock with period=10
// A testbench
initial begin
#5 rst = 1'b1; // rst is active low
#5 d1 = 1'b1;
#5 d1 = 1'b0;
#15 d2 = 1'b1;
#5 d2 = 1'b0;
#25 sel = 1'b1;
#10 d2 = 1'b1;
#5 d2 = 1'b0;
#15 d2 = 1'b1;
#5 d2 = 1'b0;
#15 d2 = 1'b1;
#5 d2 = 1'b0;
#20 $finish();
end
//end
initial begin
$dumpfile("out.vcd");
// This will dump all signal, which may not be useful
//$dumpvars;
// dumping only this module
//$dumpvars(1, testbench);
// dumping only these variable
// the first number (level) is actually useless
$dumpvars(0, testbench);
end
seller2 t(.clk(clk),
.rst(rst),
.d1(d1),
.d2(d2),
.sel(sel),
.out1(out1),
.out2(out2),
.out3(out3)
);
endmodule