将 verilog 或 systemverilog 中 2x 时钟输入的数据转换为 1x 时钟

发布于 2024-10-31 19:12:20 字数 177 浏览 2 评论 0原文

我正在致力于验证。我当前面临一个问题,即将 2x 时钟内的数据转换为一个单元。

对于 132 位信号,它以 2x 时钟作为 66 位总线传输。

再次接收时,所有时钟转换将从 2x 到 1x 完成,以取回信号的所有 132 位。

有人可以帮助我如何做到这一点吗?

预先非常感谢。

I am working on validation. I current face a problem of converting a data that is coming to a unit in 2x clock.

For a signal of 132 bits it travels as 66 bit bus in 2x clock.

At receiving again all the clock conversion is to be done from 2x to 1x getting back all 132 bits of the signal.

Can somebody help me on how to do this ?

Thanks a lot in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

莳間冲淡了誓言ζ 2024-11-07 19:12:20

通常的方法是你有一个 132 位双端口寄存器。一个端口位于 1x 时钟域中,另一个端口位于 2x 时钟域中。由于一个是只读的,一个是只写的,所以可以像普通寄存器一样描述它。但不同时钟域之间的迁移非常棘手,尤其是。因为亚稳态。要解决此问题,您必须添加另一级触发器(即另一个寄存器)。

我的回答不是很具体和详细,但这是因为您的问题非常不具体/广泛。

The usual way is that you have a 132 bit dual ported register. With one port in your 1x clock domain and and the other port in your 2x clock domain. As one is read only and one write only, you can just describe it like a normal register. But migrating between different clock domains is very tricky, esp. because of metastability. Do workaround this you have to add another level(s) of flip flops (i.e. another register).

My answer is not very specific and detailed, but this due to the fact, that your question is very unspecific/broad.

神回复 2024-11-07 19:12:20

这是一篇关于时钟域交叉技术的优秀论文。

Here's an excellent paper on clock domain crossing techniques.

蒗幽 2024-11-07 19:12:20

由于问题被标记为 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

:输出时钟不同步,我认为您需要在输入时钟域中切换标志信号,该信号必须与输出时钟域双同步并传递到输出逻辑。当输出侧逻辑检测到切换时,它可以读取 data_out,并且必须设置另一个标志信号,该信号必须双同步并传递到输入侧逻辑。在输入逻辑看到第二个标志切换之前,我认为它不应该改变data_in

Since the question is tagged verilog & system-verilog I assume a Verilog module to do the conversion is desired.

Assuming the input & output clocks are synchronous, here is the code (not well-tested, may need some tweaks):

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

I tested this with this stimulus:

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

If the input & output clocks are not synchronous, I think you will need to toggle a flag signal in the input clock domain which has to be double-sync'd to the output clock-domain and passed to the output logic. When the output-side logic detects the toggle, it can read data_out and will have to set another flag signal which has to be double-sync'd and passed on to the input-side logic. Until the input logic sees this second flag toggle I think it should not change data_in.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文