Verilog Finite State Machine
Я пытаюсь создать конечный автомат в Verilog. В системе 4 1-bit
входные rst
, clk
, A
, B
и один выход, Z
,
Z равно 1, если либо: A имел одинаковое значение на последних двух фронтах тактового сигнала.
или B был высоким (1) на каждом фронте тактового сигнала с момента последнего правила.
Иначе z=0
;
У меня нет инструментов для имитации моих попыток. Так что мне интересно, если это правильный метод и я на правильном пути?
module StateMachine( R, A, B, clk, Z);
input R, A, B, clk;
output reg Z;
reg ATemp;
reg state;
always @ (posedge clk or A)
if (A == 1'b1)
/////////////////
begin
if (ATemp == 1'b1) state <= 1'b1;
else ATemp <= A;
end
////////////////
else
////////////
begin
if (ATemp == 1'b0) state <= 1'b1;
else ATemp <= A;
end
always @ (state)
case(state)
1'b0: Z=0;
1'b1: Z=1;
default: Z=0;
endcase
endmodule
3 ответа
Вы можете использовать следующие инструменты:
GHDL - это симулятор с открытым исходным кодом для языка VHDL ( Руководство пользователя)
Кроме того, это самые популярные инструменты моделирования:
Другие ресурсы:
Существует также сообщество электроники stackexchange и codereview.
- Overmapped: форум по темам VHDL
Кроме того, обратите внимание на инструмент компилятора C to HDL
(.. Я сомневаюсь, что многие могут просмотреть ваш код за 3 минуты, и я бы тоже их не хотел)
Ваше определение триггера немного неверно. У тебя есть always @ (posedge clk or A)
, Вы не должны комбинировать триггеры края и не-триггеры края. Это может работать в симуляции, но вы не получите то, что вы хотите в синтезе.
Если вы хотите, чтобы значение изменялось только по фронту тактовой частоты, используйте always @( posedge clk)
или для комбинаторного ввода, то есть выход изменяется с использованием ввода always @( A )
или более современная версия always @*
, @* сработает для любых изменений. Пропущенные элементы из списка чувствительности используются в качестве основной причины для синтезированного кода, не имитирующего то же самое, что RTL.
Сказав, что если вы строите триггер, вы должны включить сброс. always @ (posedge clk or negedge rst_n)
Также обратите внимание, что состояние никогда не устанавливается на 0, поэтому первое впечатление состоит в том, что это будет привязано к определенному состоянию / выходу. Мне трудно понять, как код реализует заданный вопрос. Мое решение будет что-то вроде:
module statemachine(
input rst,
input A,
input B,
input clk,
output reg Z
);
reg [1:0] a_last_two;
wire rule_one;
always @ (posedge clk or negedge rst) begin
if (~rst) begin
a_last_two <= 2'b0;
end
else begin
a_last_two <= {a_last_two[0] ,A};
end
end
assign rule_one = (a_last_two[1] == a_last_two[0]);
//rule one could be written as ~^a_last_two (xnor reduction operator)
reg rule_two;
always @ (posedge clk or negedge rst) begin
if (~rst) begin
rule_two <= 1'b0 ;
end
else begin
//rule 2 resets when rule_one is true
if (rule_one) begin
rule_two <= 1'b1 ;
end
else begin
rule_two <= rule_two & B ;
end
end
end
assign Z = rule_one | rule_two ;
endmodule
У вас нет логики следующего состояния, поэтому состояние никогда не изменится, и нет сброса, поэтому состояние будет начинаться с 1'bz. Я рекомендую начинать с рекомендаций Xilinx при кодировании конечных автоматов.