我正在验证。我目前面临一个将数据转换为 2x 时钟单元的问题。
对于 132 位信号,它以 2x 时钟作为 66 位总线传输。
再次接收时,所有时钟转换都将完成从 2x 到 1x 的所有 132 位信号。
有人可以帮助我如何做到这一点吗?
提前非常感谢。
我正在验证。我目前面临一个将数据转换为 2x 时钟单元的问题。
对于 132 位信号,它以 2x 时钟作为 66 位总线传输。
再次接收时,所有时钟转换都将完成从 2x 到 1x 的所有 132 位信号。
有人可以帮助我如何做到这一点吗?
提前非常感谢。
通常的方法是你有一个 132 位双端口寄存器。一个端口位于 1x 时钟域,另一个端口位于 2x 时钟域。由于一个是只读的,一个是只写的,你可以把它描述成一个普通的寄存器。但是在不同的时钟域之间迁移非常棘手,尤其是。因为亚稳态。要解决此问题,您必须添加另一个级别的触发器(即另一个寄存器)。
我的回答不是很具体和详细,但这是因为您的问题非常不具体/广泛。
这是一篇关于时钟域交叉技术的优秀论文。
由于问题已标记并且我假设需要一个 Verilog 模块来进行转换verilog
。system-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
如果输入和输出时钟不同步,我认为您需要在输入时钟域中切换一个标志信号,该信号必须双同步到输出时钟域并传递给输出逻辑。当输出侧逻辑检测到切换时,它可以读取data_out
并且必须设置另一个标志信号,该信号必须被双同步并传递给输入侧逻辑。在输入逻辑看到第二个标志切换之前,我认为它不应该改变data_in
。