【问题标题】:change verilog 16x4 unidirectional mux to bidirectional mux将 verilog 16x4 单向多路复用器更改为双向多路复用器
【发布时间】:2013-12-16 06:08:35
【问题描述】:

我编写了以下代码来实现四个 16:4 多路复用器:

module coder(
    selCh0, selCh1, selCh2, selCh3, 
    outCh0, outCh1, outCh2, outCh3,
    inEnc0, inEnc1, inEnc2, inEnc3
);
    input  wire [1:0] selCh0, selCh1, selCh2, selCh3;
    output wire [3:0] outCh0, outCh1, outCh2, outCh3;
    input  wire [3:0] inEnc0, inEnc1, inEnc2, inEnc3;

    mux_16x4 ch0(selCh0, inEnc0, inEnc1, inEnc2, inEnc3, outCh0);
    mux_16x4 ch1(selCh1, inEnc0, inEnc1, inEnc2, inEnc3, outCh1);
    mux_16x4 ch2(selCh2, inEnc0, inEnc1, inEnc2, inEnc3, outCh2);
    mux_16x4 ch3(selCh3, inEnc0, inEnc1, inEnc2, inEnc3, outCh3);
endmodule

module mux_16x4(sel, enc0, enc1, enc2, enc3, out);
    input wire [1:0] sel;
    input wire [3:0] enc0, enc1, enc2, enc3;
    output reg [3:0] out;

    always @(sel, enc0, enc1, enc2, enc3)
    begin
        case ({sel})
            2'b00: out <= enc0;
            2'b01: out <= enc1;
            2'b10: out <= enc2;
            2'b11: out <= enc3;
            default: out <= 4'b0;
        endcase;
    end
endmodule

我的问题有两个:

  1. 有没有更有效和/或更好的方法来做到这一点?我正在学习,所以我写的代码没有任何特殊问题,但我想我会检查一下是否可以改进。
  2. 我需要反转每个 4:1 多路复用器的第四位。现在,每个 inEncN 总线中的每一位都是输入,而每个 outChY 总线中的每一位都是输出。我一开始是这样写的,看看它是否能工作,但真正的硬件需要一个信号才能走另一条路。

为了更简洁,我将使用一组特定的信号进行解释。现在,outCh0[3:0] 中的位都是输出。我真的需要 outCh0[3] 作为输入,并将其映射到选择信号选择的任何 inEncN[3] 总线。因此,我还需要将所有 inEncN[3] 信号作为输出,而不是像每个相应总线中的其他三位那样作为输入。

我尝试制作所有有问题的总线 inout 而不是 inputoutput,但无论我尝试什么,我都无法编译。

上面显示的代码编译为 32 个逻辑元素,剩下 8 个备用。将代码放入 40 个或更少的逻辑元素中将是一个巨大的胜利,但我有一个可以接受的 B 计划。

任何帮助将不胜感激。

【问题讨论】:

  • 你是什么意思“outCh0[3] 作为输入并映射到任何 inEncN[3] 总线被选择”?在我看来,这与sel 相同。

标签: verilog mux


【解决方案1】:

你不需要任何双向信号,你只需要重新定义你的端口。使用系统verilog,您可以将多维数组作为端口传递,这将使该代码更加紧凑。您还可以创建结构以在一个对象中包含 3 个输入和 1 个输出。但是,这是一个 verilog 问题,所以我们会这样做:

module coder(
  selCh0, selCh1, selCh2, selCh3, 
  outCh0, outCh1, outCh2, outCh3,
  inCh0, inCh1, inCh2, inCh3,
  inEnc0, inEnc1, inEnc2, inEnc3,
  outEnc0, outEnc1, outEnc2, outEnc3      
);
  input  [1:0] selCh0, selCh1, selCh2, selCh3;

  input  [2:0] inEnc0, inEnc1, inEnc2, inEnc3;
  output       outEnc0, outEnc1, outEnc2, outEnc3;

  output [2:0] outCh0, outCh1, outCh2, outCh3;
  input        inCh0, inCh1, inCh2, inCh3;

  wire [2:0] inEnc [0:3];
  wire       inCh [0:3];

  assign inEnc[0] = inEnc0;
  assign inEnc[1] = inEnc1;
  assign inEnc[2] = inEnc2;
  assign inEnc[3] = inEnc3;

  assign inCh[0] = inCh0;
  assign inCh[1] = inCh1;
  assign inCh[2] = inCh2;
  assign inCh[3] = inCh3;

  assign outCh0 = inEnc[selCh0];
  assign outCh1 = inEnc[selCh1];
  assign outCh2 = inEnc[selCh2];
  assign outCh3 = inEnc[selCh3];

  assign outEnc0 = inCh[selCh0];
  assign outEnc1 = inCh[selCh1];
  assign outEnc2 = inCh[selCh2];
  assign outEnc3 = inCh[selCh3];

endmodule

这是在系统 verilog 中使用数组作为端口重复的。这也被参数化以实现通道数的灵活性。由于通道数可能不是 2 的幂,我们必须检查 selCh 是否为合法值。如果不是,则为输出分配一个默认值。 $clog2 函数用于计算从NUMCH 输入中选择所需的最小位数:

module coder #(parameter NUMCH=4) (
  input [$clog2(NUMCH)-1:0] selCh[NUMCH],

  input      [2:0] inEnc[NUMCH],
  output reg       outEnc[NUMCH],

  output reg [2:0] outCh[NUMCH],
  input            inCh[NUMCH]
  );

  always_comb begin
    for (int i=0; i<NUMCH; i++) begin
      if(selCh[i]<NUMCH) begin
        outCh[i] = inEnc[selCh[i]];
        outEnc[i] = inCh[selCh[i]];
      end
      else begin
        outCh[i] = '0;
        outEnc[i] = '0;
      end
    end
  end
endmodule

【讨论】:

  • 感谢您的精彩解释和代码!我想我理解您在 System Verilog 示例中所说的内容。它当然看起来更干净,更易于维护。我认为必须有一种方法来使用多维数组,但我想不通。这个答案在几个方面确实对我有帮助。
  • 如果你可以使用系统verilog语法,我会去的。据我所知,我使用的工具(VCS 和 Incisive)都完全支持它。有时您必须使用 verilog 来完成这种事情,这确实使您难以理解代码。我会坚持设计简单的东西,因为您很容易进入无法综合的领域,因为 SV 语言有许多仅用于验证的功能。
猜你喜欢
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多