Обнаружение пика Verilog
Я новичок в Verilog. Я пытаюсь определить пиковое напряжение входного сигнала для АЦП на ПЛИС. До этого я хотел протестировать простой, но похожий код, который находит минимум и максимум набора из 4-битных параллельных входов.
Изначально я назначил pk_low
а также pk_high
в качестве первого входа, в зависимости от предстоящих входов pk_low
а также pk_high
должен измениться или остаться прежним. Но в симуляции я вижу, что pk_low
значение всегда 0. pk_high
а также pp_voltage
(пиковое напряжение) неизвестны (X).
В чем проблема?
module peak_voltage (clk, parallel_in, pk_high, pk_low, pp_voltage);
input clk;
input wire [3:0] parallel_in;
output reg [3:0] pk_high;
output reg [3:0] pk_low;
output wire [3:0] pp_voltage;
reg state;
parameter st0 = 'd0;
parameter st1 = 'd1;
parameter st2 = 'd2;
initial begin
state = st0;
pk_high <= parallel_in;
pk_low <= parallel_in;
end
always @ (posedge clk) begin
if (parallel_in > pk_high)begin
state = st1;
end else if (parallel_in < pk_low) begin
state = st2;
end else begin
state = st0;
end
end
always @(*) begin
case (state)
st0: begin
pk_low <= pk_low;
pk_high <= pk_high;
end
st1: begin
pk_low <= pk_low;
pk_high <= parallel_in;
end
st2: begin
pk_low <= parallel_in;
pk_high <= pk_high;
end
endcase
end
assign pp_voltage = pk_high - pk_low;
endmodule
2 ответа
Вы закодировали это как конечный автомат, где вместо этого у вас должно быть постоянное назначение для вашего селектора дел. Присвойте 3 бита, чтобы получился горячий вектор.
У вас есть неблокирующие назначения в этой логике - вам нужно использовать блокировку для комбинаторной логики.
Вам не хватает явного хранилища для пиковых значений максимума / минимума. Может быть, вы могли бы сделать некоторые защелки в этом стиле, но не совсем понятно, что вы имели в виду.
Определите некоторые флопы, синхронизированные с помощью clk, с неблокирующими назначениями. Захватите обновленные результаты в каждом цикле.
Помните, что verilog выполняет все операторы параллельно, вы не должны думать о порядке выполнения. Вместо этого подумайте о явном захвате ваших результатов и вычислении "следующих" значений для этих результатов.
Вы можете просмотреть свой код как:
- Проверьте обновление высокого или низкого
- Рассчитать новые значения
- Захват новых ценностей
Вы сделали (1) неправильно, и пропустили (3) в целом. Возможно, имеет смысл кодировать (1) и (2) вместе, но это зависит от того, как вы хотите выразить функции.
assign new_level = (in > level) ? in : level;
Вы не обновляете значения pk_high/pk_low недавно обновленным parallel_in в своем всегда блоке. Здесь нет необходимости использовать состояния. После обновления всего внутри всегда блока вы можете напрямую вычесть пиковые значения, чтобы получить напряжение pp в конце