Состояния на этом компьютере FSM изменяются слишком быстро из-за проблемы с обновлением текущего состояния часов.
Я нахожусь в процессе реализации конечного автомата в Verilog, и я столкнулся с проблемой. Тем не менее, я знаю, в чем проблема, но я не уверен, как это исправить.
Это мой текущий код:
module moore_SM(clk, rstn, btn, z, rstLED, state);
//Port Assignments
input clk, rstn;
input [2:0] btn;
output z;
output reg rstLED;
output reg [5:0] state;
//Internal Port Assignments
reg [1:0] w, x; //NOTE: This is typically the input in FSM,
//but it is internal because there is a conversion from btn to w.
reg [2:0] y, Y; //Present state and next state respectively
reg [2:0] pstBtn;
reg [31:0] cnt;
//Define some parameters
//Input Type (i.e. A, B or C)
parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b11, DC = 2'b10; //DC => don't care - shouldn't affect FSM
//State (i.e. S1, S2, S3, S4, S5 or S6)
parameter [2:0] S1 = 3'b000, S2 = 3'b001, S3 = 3'b010, S4 = 3'b011, S5 = 3'b100, S6 = 3'b101;
initial begin
state = 0;
end
//Determine which button is active
always @(*)
begin
case(btn)
3'b110: begin w = A; end
3'b101: begin w = B; end
3'b011: begin w = C; end
// default: w = DC;
endcase
end
//Define the next state and output combinational circuits
always @(w,y)
begin
case(y)
S1: begin
state = 6'b000001;
if(w == A) begin Y = S2; end
else begin Y = S1; end
end
S2: begin
state = 6'b000010;
if(w == B) begin Y = S3; end
else begin if(w == A) begin Y = S2; end
else Y = S1; end
end
S3: begin
state = 6'b000100;
if(w == A) begin Y = S2; end
else begin if(w == B) begin Y = S4; end
else Y = S1; end
end
S4: begin
state = 6'b001000;
if(w == A) begin Y = S5; end
else begin Y = S1; end
end
S5: begin
state = 6'b010000;
if(w == A) begin Y = S2; end
else begin if(w == B) begin Y = S3; end
else Y = S6; end
end
S6: begin
state = 6'b100000;
if(w == A) begin Y = S2; end
else begin Y = S1; end
end
//default: Y = 3'b111;
endcase
end
//assign z = (Y == S2);
//Define the sequential block
always @(posedge clk)
begin
y <= Y;
end
endmodule
Этот код должен идентифицировать шаблон ABBAC. Я считаю, что логика выполняет эту цель.
Однако я столкнулся с проблемой. Когда я нажимаю одну из трех кнопок, первая всегда блокируется -always @(*)
- выполняет и оценивает изменение. Состояние кнопки кодируется и сохраняется вw.
В то же время следующий всегда блок -always @(w,y)
- чувствует изменение и определяет, в каком состоянии находиться. Как я и ожидал, если я отправлю входA
машина движется отS1
вS2
.
Теперь, если я отправлю входB
, машина возвращается в состояниеS1
, После того, как я изменил несколько вещей вокруг, я определил то, что я считаю проблемой. Обратите внимание на последний всегда блок:always @(posedge clk).
Этот блок постоянно обновляет текущее состояние,y.
Когда я нажимаю кнопку, я предполагаю, что происходит то, что второй всегда блокирует,always @(w,y),
получает обновленныйy
на 50 мГц (в моем случае), что, очевидно, намного быстрее, чем я могу нажать и отпустить кнопку. Предполагая, что я нажимаюB
кнопка в то время как в состоянииS2
состояние быстро меняется наS3
вS4
а затемS1
из-за постоянного обновления.
Тем не менее, у меня возникли некоторые проблемы, связанные с решением этой проблемы. Мне в принципе нужен какой-то способ изменить только одно состояние за нажатие кнопки.
Обратите внимание, что я в основном тестирую этот код на экспериментальной плате. Я написал тестовый стенд, но симуляция, похоже, не соответствует тому, что я вижу на панели дизайна. Если кто-то захочет увидеть код тестового стенда, я разместил его ниже:
`timescale 1ns/1ns
module moore_SM_TB();
reg clk;
reg [2:0] btn;
wire [5:0] state;
wire z;
wire rstLED;
initial begin
clk = 1;
#0 btn = 3'b111;
#50 btn = 3'b110;
#50 btn = 3'b111;
#50 btn = 3'b101;
#50 btn = 3'b111;
#50 btn = 3'b011;
#50 btn = 3'b111;
end
always begin
#20 clk = ~clk;
end
//MUT
moore_SM MUT (clk, 0, btn, z, rstLED, state);
endmodule
ПРИМЕЧАНИЕ: я считаю, что решение в конечном итоге будет включать изменение способа обработки кнопок. Когда я отпускаю кнопку, это также регистрируется как изменение. Следовательно, я должен был закомментировать случай по умолчанию, потому что это также испортило бы, в каком состоянии находится машина.
ОБНОВЛЕНИЕ: я написал сокращенную версию FSM, которую я разместил выше, чтобы попытаться отладить код. Он пытается обнаружить последовательность AB.
module moore_SM(clk, btn, rstN, state, rstLED);
//Port assignments
input clk;
input rstN;
input [2:0] btn;
output reg rstLED;
output reg [5:0] state;
//Internal Port Assignments
reg [1:0] w;
reg [2:0] y, Y;
reg [2:0] pstBtn;
//Define some parameters
parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b11, DC = 2'b10;
parameter [2:0] S1 = 3'b000, S2 = 3'b001, S3 = 3'b010, S4 = 3'b011, S5 = 3'b100, S6 = 3'b101;
//Initialize some values to prevent Quartus from doing
initial
begin
y = S1;
Y = y;
state = 0;
rstLED = 0;
end
always @(*)
begin
if(btn == pstBtn) begin w = DC; end
else begin
case(btn)
3'b110: w = A;
3'b101: w = B;
3'b011: w = C;
default: w = DC;
endcase
end
end
always @(*)
begin
case(y)
S1: begin
state = 6'b000001;
if(w == A) begin Y = S2; end
else begin Y = S1; end
end
S2: begin
state = 6'b000010;
if(w == B) begin Y = S3; end
if(w == DC) begin Y = S2; end
else begin Y = S1; end
end
S3: begin
state = 6'b000100;
if(w == DC) begin Y = S3; end
else begin Y = S1; end
end
default: begin state = 6'b100000; Y = S1; end
endcase
end
//Update state and check for reset signal
always @(posedge clk, negedge rstN)
begin
pstBtn <= btn;
if(rstN == 0) begin y <= S1; rstLED <= 1; end
else begin y <= Y; rstLED <= 0; end
end
endmodule
Обратите внимание, что я пытаюсь «сэмплировать» состояние кнопки в последнем блоке всегда. Я использовал этот метод в прошлом, но, похоже, он здесь не работает. Всякий раз, когда я нажимаю кнопку, состояние не меняется. Мне интересно, если это проблема времени сейчас.