我正在编写用于在FPGA上实现的UART的Verilog代码,并且在第一个之后同步到START位字节时遇到一些麻烦。
我的经理建议同步我接收到的信号,并使用某种中断作为与我的FSM通信的方式,以确认已启动。
我已经阅读了关于上升沿检测的技术,我觉得我可以这样做:
module StartDetectionUnit (
input clk, state, signal_in,
output trigger
);
reg signal_d;
always @(posedge clk)
begin
signal_d <= signal_in;
end
assign trigger = signal_in & (!signal_d);
endmodule
根据我的理解,这样的描述会检测到RISING边缘,而不是FALLING边缘,但RS-232通信中的“START”是逻辑“0”。
另外,我想在IDLE状态[硬编码为000]时实际分配标志,但对最终作业进行疯狂选通对我来说听起来并非硬件。
tldr,两个问题
非常感谢,我是Verilog的新手,也是HDL的新手
答案 0 :(得分:1)
如果您的信号signal_in来自您的设计之外,它将无法正确同步。在您的设计中,您只使用一个d-latch,需要两个。
reg signal_d;
always @(posedge clk)
begin
signal_d <= signal_in;
end
这将只合成一个d锁存器。要正确同步信号,必须为两个d-latch实例化声明第二个信号:
reg signal_d;
reg signal_sync;
always @(posedge clk)
begin
signal_d <= signal_in;
signal_sync <= signal_d;
end
并且不应在您的设计中使用signal_d。然后要进行边缘检测,你必须声明第三个信号:
reg signal_d;
reg signal_sync;
reg signal_sync_old;
always @(posedge clk)
begin
signal_d <= signal_in;
signal_sync <= signal_d;
signal_sync_old <= signal_sync;
end
对于下降沿检测,请执行:
assign trigger = signal_sync_old & (!signal_sync);
有关同步的更多信息的好网站: https://www.doulos.com/knowhow/fpga/synchronisation/
据我了解,您的信号'状态'以3位编码,然后您可以执行:
assign trigger = (state == 3'b000) ? (signal_sync_old & (!signal_sync)):0;
答案 1 :(得分:0)
我有同样的问题。我认为当您的主时钟采样率很高时,基本的下降沿检测将失败。传入的波特信号从高电平变为低电平需要花费时间。一旦检测到高低转换(在下降的波特信号的中间),就有可能在实际达到最终的低值之前再次尝试检测到它。在这种情况下,您将具有从低到低的检测率,因此丢失了下降过渡。我要解决的方法是在检测到下降沿时立即将检测器锁住,以便必须手动重启才能检测到第二次。
答案 2 :(得分:-3)