题解 | #脉冲同步电路#
脉冲同步电路
https://www.nowcoder.com/practice/b7f37e6c55e24478aef4ec2d738bbf07
之前看达尔文求职系列学习过,所以自己还是写出来了。
但是一开始忘了data_in_reg <= data_in ? (~data_in_reg) : data_in_reg;
注意点1:data_in_reg <= data_in ? (~data_in_reg) : data_in_reg;把脉冲信号变成沿信号。
注意点2:打三拍才可以,data_slow1 刚同步过来,直接做assign dataout = data_slow2 ^ data_slow3;可能结果不稳定
注意点3:需要通过assign进行dataout赋值。
借用题解讨论区图片:因为使用了assign,整体效果相当于打两拍
借用题解讨论区图片:因为使用了assign,整体效果相当于打两拍
改进解法2:
改进点:使用reg [2:0] data_slow;
讨论区有人提出的问题:
我觉得这个题目的答案有两个问题,
1.因为题目中并没有规定data_in脉冲的长度,假如data_in脉冲的长度超过三个T_clkfast,快时钟域采集到的脉冲就会是多个脉冲。正常的沿检测应该采用答案中快慢时钟域脉冲同步的方法。
2.由于慢时钟域的频率是快时钟域的10倍,如果初始脉冲出现的时机不凑巧,满时钟域是采集不到相应的脉冲的,保证同步成功应该将快时钟域中的脉冲变成沿信号或者展宽到大于T_clkslow.
`timescale 1ns/1ns module pulse_detect( input clk_fast , input clk_slow , input rst_n , input data_in , output dataout ); reg data_in_reg; reg [2:0] data_slow; always @ (posedge clk_fast, negedge rst_n) begin if(!rst_n) begin data_in_reg <= 1'b0; end else begin data_in_reg <= data_in ? (~data_in_reg) : data_in_reg; end end always @ (posedge clk_slow, negedge rst_n) begin if(!rst_n) begin data_slow <= 3'b0; end else begin data_slow <= {data_slow[1:0], data_in_reg}; end end assign dataout = data_slow[2] ^ data_slow[1]; // assign dataout = data_slow1 ^ data_slow2; endmodule
`timescale 1ns/1ns module pulse_detect( input clk_fast , input clk_slow , input rst_n , input data_in , output dataout ); reg data_in_reg, data_slow1, data_slow2,data_slow3; always @ (posedge clk_fast, negedge rst_n) begin if(!rst_n) begin data_in_reg <= 1'b0; end else begin data_in_reg <= data_in ? (~data_in_reg) : data_in_reg; end end always @ (posedge clk_slow, negedge rst_n) begin if(!rst_n) begin data_slow1 <= 1'b0; data_slow2 <= 1'b0; data_slow3 <= 1'b0; end else begin data_slow1 <= data_in_reg; data_slow2 <= data_slow1; data_slow3 <= data_slow2; end end assign dataout = data_slow2 ^ data_slow3; // assign dataout = data_slow1 ^ data_slow2; endmodule