目录

背景

原题复现

审题

我的设计1

我的设计2


背景

曾经专门写过这个话题,可是今天在练习HDLBits时候,又发现了这个问题,但是以前的思路我已经忘了,不得不回顾。

FPGA中如何实现双边沿采样?

奇怪的是我竟然之前用过的方法,今天我已经想不通为什么了?


直接见原题吧:

原题复现

You're familiar with flip-flops that are triggered on the positive edge of the clock, or negative edge of the clock. A dual-edge triggered flip-flop is triggered on both edges of the clock. However, FPGAs don't have dual-edge triggered flip-flops, and always @(posedge clk or negedge clk) is not accepted as a legal sensitivity list.

Build a circuit that functionally behaves like a dual-edge triggered flip-flop:

HDLBits 系列(15) 如何设计一个双边沿采样的电路?_触发器

(Note: It's not necessarily perfectly equivalent: The output of flip-flops have no glitches, but a larger combinational circuit that emulates this behaviour might. But we'll ignore this detail here.)

审题

(注意:它不一定完全等效:触发器的输出没有毛刺,但是可以模仿这种行为的较大的组合电路。但是在这里我们将忽略此细节。)

上面注意的意思是可以接受毛刺。

我还是说一下自己的思路吧,本身最容易想到的方法应该是:

always@(posedge clk or negedge clk) begin
    q  <= d;
end

但是由于不存在这样的触发器,所以编译器是过不去的,不能这样做。

那这样呢?

always@(posedge clk) begin
    q <= d;
end

always@(negedge clk) begin
    q <= d;
end

这不是废话吗?这和上面的写法没什么区别?属于掩耳盗铃。

对时钟做文章:

assign clk_gen = ~clk;
always@(posedge clk) begin
    q <= d;
 
end
 
always@(posedge clk_gen) begin
    q <= d;
end

综合工具不能综合,同样属于掩耳盗铃之举动。

生成的时钟clk_gen和clk直接相关,然后对同一个reg变量进行赋值,无异于同一个时钟上下边沿进行赋值。

那我们对reg变量动手,用不同的reg变量代表输出,之后进行逻辑运算。

我的设计1

给出一种可行的方案:

module top_module (
    input clk,
    input d,
    output q
);
    reg p = 0, n = 0;
 
always@(posedge clk) begin
    n <= d;
end
 
always@(negedge clk ) begin
	p <= d;
end
 
assign q = clk ? n : p;


endmodule

我的设计2

最后还有一种可行的方案:

module TwoEdge(
    input clk,
    input rst_n,
    input d,
    input out
 
);
 
reg p = 0, n = 0;
 
always@(posedge clk) begin 
    p <= d ^ n;
end
 
always@(negedge clk ) begin
    n <= d ^ p;
 
end
 
assign out = p ^n;
 
 
 
endmodule

但此刻我心力交瘁,竟想不出为什么了?

2019年11月24(周日),21:57(这个日子过后,我将又是一个状态)。