我正在进行验证。我目前面临的问题是转换到2x时钟内的数据。
对于132位信号,它在2x时钟内作为66位总线传输。
再次接收时,所有时钟转换都需要从2x到1x完成,并取回信号的所有132位。
有人可以帮我解决这个问题吗?
提前多多感谢。
答案 0 :(得分:1)
通常的方法是你有一个132位双端口寄存器。在1x时钟域中有一个端口,在2x时钟域中有另一个端口。由于一个是只读的而一个是只写的,所以你可以像普通寄存器一样描述它。但是,在不同的时钟域之间迁移是非常棘手的,尤其是。因为亚稳态。要解决这个问题,你必须添加另一个级别的触发器(即另一个寄存器)。
我的回答并不是非常详细和详细,但这是因为您的问题非常不明确/广泛。
答案 1 :(得分:1)
Here's关于时钟域交叉技术的优秀论文。
答案 2 :(得分:1)
由于问题被标记为verilog
& system-verilog
我假设需要一个Verilog模块进行转换。
假设输入&输出时钟是同步的,这里是代码(没有经过充分测试,可能需要一些调整):
module conv_2x_to_1x (rst, clk_in, data_in, clk_out, data_out);
parameter IN_WIDTH = 66;
input wire rst, clk_in, clk_out;
input wire [IN_WIDTH-1:0] data_in;
output reg [2*IN_WIDTH-1:0] data_out;
localparam LOWER_HALF = 0, UPPER_HALF = 1;
reg [2*IN_WIDTH-1:0] data_tmp;
reg half;
always @(posedge clk_in or posedge rst)
if (rst) begin
data_tmp <= {2*IN_WIDTH {1'b0}};
half <= LOWER_HALF;
end else if (half == LOWER_HALF) begin
data_tmp [IN_WIDTH-1:0] <= data_in;
half <= UPPER_HALF;
end else begin
data_tmp [2*IN_WIDTH-1:IN_WIDTH] <= data_in;
half <= LOWER_HALF;
end
always @(posedge clk_out or posedge rst)
data_out <= rst ? {2*IN_WIDTH {1'b0}} : data_tmp;
endmodule
我用这种刺激测试了这个:
module test;
reg rst;
reg [1:0] clk;
reg [65:0] data_in;
wire [131:0] data_out;
conv_2x_to_1x conv_2x_to_1x (rst, clk[0], data_in, clk[1], data_out);
always #5 clk = clk + 2'b01;
initial begin
$monitor ("%3t: %1b, %2b, %66h, %66h %66h", $time, rst, clk, data_in,
data_out [131:66], data_out [65:0]);
clk = 2'b00;
#2 rst = 1'b1;
@ (negedge clk [0]) #2 begin
rst = 1'b0;
data_in = 66'h2d_eadbe_efcaf_ebabe;
end
@ (negedge clk [0]) #2 data_in = 66'h1b_adc0f_fedea_dc0de;
@ (negedge clk [0]) #2 data_in = 66'h3c_afeba_bedea_dbeef;
@ (negedge clk [0]) #2 data_in = 66'h0d_eadc0_debad_c0ffe;
#12 $finish;
end
endmodule
如果输入&amp;输出时钟不是同步的,我想你需要在输入时钟域中切换一个标志信号,该信号必须与输出时钟域双同步并传递给输出逻辑。当输出端逻辑检测到切换时,它可以读取data_out
并且必须设置另一个必须双同步的标志信号并传递给输入端逻辑。在输入逻辑看到第二个标志切换之前,我认为它不应该改变data_in
。