Это мой код Verilog:
//state reg
(* syn_encoding = "safe" *)reg [3:0] ns_sig, cs_sig;
//state parameters
localparam
sLOW = 4'b0001,
sTO_HIGH = 4'b0010,
sHIGH = 4'b0100,
sTO_LOW = 4'b1000;
always @(posedge clk or negedge rst_n)
if (!rst_n)
cs_sig <= sLOW;
else
cs_sig <= ns_sig;
always @(*)
begin
ns_sig = cs_sig;
case (cs_sig)
sLOW:
if (sig == `HIGH)
ns_sig = sTO_HIGH;
sTO_HIGH:
if (valid_HIGH == `ON)
ns_sig = sHIGH;
else if (sig == `OFF)
ns_sig = sLOW;
sHIGH:
if (sig == `OFF)
ns_sig = sTO_LOW;
sTO_LOW:
if (valid_LOW == `ON)
ns_sig = sLOW;
else if (sig == `ON)
ns_sig = sHIGH;
default:
ns_sig = sLOW;
endcase
end
always @(posedge clk)
begin
if (cs_sig == sTO_HIGH)
cnt_HIGH <= cnt_HIGH + {{(pWIDTH-1){1'b0}}, 1'b1};
else
cnt_HIGH <= {(pWIDTH){1'b0}};
end
assign
valid_HIGH = (cnt_HIGH == pHIGH_DEPTH -1)? `ON:`OFF;
always @(posedge clk)
begin
if (cs_sig == sTO_LOW)
cnt_LOW <= cnt_LOW + {{(pWIDTH-1){1'b0}}, 1'b1};
else
cnt_LOW <= {(pWIDTH){1'b0}};
end
assign
valid_LOW = (cnt_LOW == pLOW_DEPTH - 1)?`ON:`OFF;
always @(posedge clk)
begin
if (cs_sig == sHIGH)
sig_sf <= `HIGH;
else if (cs_sig == sLOW)
sig_sf <= `LOW;
end
Это блок фильтра двоичных сигналов, предназначенный для устранения сбоев на физическом порту, и в то же время может использоваться в качестве задержки.
Он хорошо работает в симуляции, но не на борту. Я запускал код на чипе Altrea EP2C35, и время от времени он давал сбои. Обычно sig_sf
будет на pLOW_DEPTH
(я установил его на 200) тактов после входа sig
, но иногда это будет всего на 2 клика позади.
Я добавил сигнал, чтобы посмотреть, что произошло, и оказалось, что конечный автомат дал сбой. Допустимые значения в signaltap: sLOW, sTO_LOW, sHIGH, s_TO_HIGH
, как я и установил. Но он перешел к 4'h1
на каком-то отрицательном фронте sig
и сбрасывается до sLOW
.
Но я не понимаю, почему, я уверен, что входная волна от генератора просто прекрасна.
Так ПОМОГИТЕ мне с этим, спасибо!!