目录
背景
曾经专门写过这个话题,可是今天在练习HDLBits时候,又发现了这个问题,但是以前的思路我已经忘了,不得不回顾。
奇怪的是我竟然之前用过的方法,今天我已经想不通为什么了?
直接见原题吧:
原题复现
Build a circuit that functionally behaves like a dual-edge triggered flip-flop:
(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(这个日子过后,我将又是一个状态)。