当输出重叠时,种类卡在输出上

时间:2016-05-24 10:26:07

标签: verilog overlap modelsim wave

我对verilog很新。 所以这是我的问题:

  

用16位寄存器实现16位ALU。该项目应符合以下要求   1.设计一个16位ALU:   设计一个16位ALU,X作为输入(例如A,B ..)并产生一个16位结果.ALU应执行以下功能。   ALU和LOGIC的最少5个操作   2.设计一个16x16位的寄存器文件   3.设计一个控制单元。

所以我的计划是制作一组在每个模块中都有操作的模块。然后我在测试台上收集它。但问题是现在。输出似乎重叠并变为红色和x。

这是我的添加模块。

module Add(A,B,Y,S,clk,enb);
  parameter BITS=8;
  input clk,enb;
  input [BITS - 5:0] S;
  input [BITS - 1:0] A ,B;
  output [BITS - 1:0] Y;
  reg [BITS - 1:0] Y;

  always @(posedge clk)
  begin
  if
    ((enb==1) || (S == 000))
  begin
   assign Y = A + B;

  end
  end

endmodule

Tolak模块(减号模块)

module Tolak(A,B,Y,S,clk,enb);
  parameter BITS=8;
  input clk,enb;
  input [BITS - 5:0] S;
  input [BITS - 1:0] A ,B;
  output [BITS - 1:0] Y;
  reg [BITS - 1:0] Y;

   always @(posedge clk)
begin
  if
    ((enb==1) || (S == 010))
  begin
  assign Y = A - B;

  end
  end
endmodule

Darab模块(乘法模块)

module Darab(A,B,Y,S,clk,enb);
  parameter BITS=8;
  input clk,enb;
  input [BITS - 5:0] S;
  input [BITS - 1:0] A ,B;
  output [BITS - 1:0] Y;
  reg [BITS - 1:0] Y;

  always @(posedge clk)
    begin
  if
    ((enb==1) || (S == 011))
begin
     assign Y = A * B;
  end
  end

endmodule

GateOr模块

module GateOr(A,B,Y,S,clk,enb);
  parameter BITS=16;
  input clk,enb;
  input [BITS - 14:0] S;
  input [BITS - 1:0] A ,B;
  output [BITS - 1:0] Y;
  reg [BITS - 1:0] Y;

  always @(posedge clk)
  begin
  if
    ((enb==1) || (S == 011))
  begin
   assign Y = A | B ;

  end
  end

endmodule

GateAnd模块

module GateAnd(A,B,Y,S,clk,enb);
  parameter BITS=16;
  input clk,enb;
  input [BITS - 14:0] S;
  input [BITS - 1:0] A ,B;
  output [BITS - 1:0] Y;
  reg [BITS - 1:0] Y;

  always @(posedge clk)
begin
  if
    ((enb==1) || (S == 100))
  begin
  assign Y = A & B;

  end
end

endmodule

这是我的测试台

module Maintb (); 
parameter SIZE=8;
reg clk, enb ;
reg [SIZE-6:0] S; 
reg[SIZE-1:0] A,B; 
wire[SIZE-1:0] Y; 

initial 
begin
    clk = 1'b0; enb = 1'b0;
end
// generate clock
always 
begin
    #(10) clk = !clk;
end
  always begin 
    //#(10);
    #10; enb = 1'b1; A=00000001; B=00000000; S=000; //add
    #(10); enb = 1'b0; 
    #10; enb = 1'b1; A=00000001; B=00000000; S=001; //tolak
    #(10); enb = 1'b0; 
    #10; enb = 1'b1; A=00000001; B=00000000; S=010; //darab
    #(10); enb = 1'b0; 
    #10; enb = 1'b1; A=00000001; B=00000000; S=011; //or
    #(10); enb = 1'b0; 
    #10; enb = 1'b1; A=00000001; B=00000000; S=100; //and
    //#(10);
  end

defparam dut.BITS = SIZE;
defparam dut1.BITS = SIZE;
defparam dut2.BITS = SIZE;
defparam gate.BITS = SIZE;
defparam gate1.BITS = SIZE;
Add dut (A,B,Y,S,clk,enb); //000
Tolak dut1 (A,B,Y,S,clk,enb); //001
Darab dut2 (A,B,Y,S,clk,enb); //010
GateOr gate (A,B,Y,S,clk,enb); //011
GateAnd gate1 (A,B,Y,S,clk,enb);//100
Endmodule

2 个答案:

答案 0 :(得分:1)

在HDL编码时注意以下几点:

  1. <=用于顺序硬件 =用于组合硬件
  2. 永远不要在内部使用或反之亦然
  3. 以适当的方式实例化模块,即
  4. <module name> #(parameter <paramters_list>) <instant_name >

    1. 指定输入转换到时钟边缘,避免使用#delay
    2. 的显式使用

      块的分层拓扑:

      enter image description here

      您可以在Image中看到,ALU是顶级实体,包含子模块,这些子模块相互连接或共享信号位于顶部。

      Testbench具有最高级别,其中 DUT 的实例(设计顶部将被测试) - 在测试中设计。

      这基本上会刺激信号进入DUT并从中获得响应。

      确保您没有从多个模块驱动相同的信号,例如,Y由ALU的add,sub,mul,AND和OR模块驱动,这需要是独立的。

      删除clk信号,因为组合电路根本不需要clk

      用tb查看你的干净代码,按照上面提到的那样进行修改:

      module Add #(parameter BITS=8)(A,B,Y,S,enb);
        input wire enb;
        input wire [2:0] S;
        input wire [BITS - 1:0] A ,B;
        output wire [BITS - 1:0] Y;
      
        assign Y = (A + B) & {BITS{enb & (S == 3'b000)}};
      
      endmodule
      
      
      module Tolak #(parameter BITS=8) (A,B,Y,S,enb);
        input enb;
        input [2:0] S;
        input [BITS - 1:0] A ,B;
        output wire [BITS - 1:0] Y;
      
        assign Y = (A - B) & {BITS{enb & (S == 3'b001)}};
      
      endmodule
      
      module Darab  #(parameter BITS=8) (A,B,Y,S,enb);
        input enb;
        input [2:0] S;
        input [BITS - 1:0] A ,B;
        output wire  [BITS - 1:0] Y;
      
        assign Y = (A * B) & {BITS{enb & (S == 3'b010)}}; // truncated to 8 bit only
      
      endmodule
      
      module GateOr  #(parameter BITS=8) (A,B,Y,S,enb);
        input enb;
        input [2:0] S;
        input [BITS - 1:0] A ,B;
        output wire[BITS - 1:0]  Y;
      
        assign Y = (A | B) & {BITS{enb & (S == 3'b011)}}; // truncated to 8 bit only
      
      endmodule
      
      module GateAnd  #(parameter BITS=8) (A,B,Y,S,enb);
        input enb;
        input [2:0] S;
        input [BITS - 1:0] A ,B;
        output wire [BITS - 1:0] Y;
      
        assign Y = (A & B) & {BITS{enb & (S == 3'b100)}}; // truncated to 8 bit only
      
      endmodule
      
      
      module Maintb (); 
      parameter SIZE=8;
      reg clk, enb ;
      reg [2:0] S; 
      reg [SIZE -1:0] A,B; 
      wire [SIZE -1:0] Y,Y1,Y2,Y3,Y4,Y5; 
      
      Add #(SIZE) dut (A,B,Y1,S,enb); //000
      Tolak #(SIZE) dut1 (A,B,Y2,S,enb); //001
      Darab #(SIZE) dut2 (A,B,Y3,S,enb); //010
      GateOr #(SIZE) gate (A,B,Y4,S,enb); //011
      GateAnd #(SIZE) gate1 (A,B,Y5,S,enb);//100
      
      assign Y = Y1 | Y2 | Y3 | Y4 | Y5;
      
      initial 
      begin
          clk = 1'b0; 
          enb = 1'b0;
          enb = 1'b0; A=8'b0000_0000; B=8'b0001_0000; S=3'b000; 
      end
      
      // generate clock
      always #10 clk = ~clk;
      
      initial
      begin 
        @(posedge clk); 
        @(posedge clk); 
        @(posedge clk); 
        @(posedge clk); 
        @(posedge clk); enb = 1'b1; A=8'b0000_0001; B=8'b0000_0010; S=3'b000; //add
        @(posedge clk); enb = 1'b0; 
        @(posedge clk); enb = 1'b1; A=8'b0000_0011; B=8'b0010_0000; S=3'b001; //tolak
        @(posedge clk); enb = 1'b0; 
        @(posedge clk); enb = 1'b1; A=8'b0000_1001; B=8'b0000_0000; S=3'b010; //darab
        @(posedge clk); enb = 1'b0; 
        @(posedge clk); enb = 1'b1; A=8'b0010_0001; B=8'b0100_0000; S=3'b011; //or
        @(posedge clk); enb = 1'b0; 
        @(posedge clk); enb = 1'b1; A=8'b1000_0001; B=8'b0000_0000; S=3'b100; //and
        @(posedge clk); enb = 1'b0; 
        @(posedge clk); enb = 1'b0; A=8'b0000_0000; B=8'b0001_0000; S=3'b000; //and
        #100 $finish;
      end
      
      initial
      begin
        $monitor("clk %b  A-%b B-%b Y-%b S-%b enb-%b",clk, A, B, Y, S, enb);
      end
      
      endmodule
      

      模拟:

      enter image description here

答案 1 :(得分:0)

对于初学者来说,模块GateOr和GateAnd在其S信号中将具有非法范围...

input [BITS - 14:0] S;

BITS = 8使它......好吧,[ - - 6:0]。除此之外,您将所有输出一次驱动到Y.鉴于您在模块中执行逻辑OR,而不是AND,所有这些都将立即激活。

我很遗憾地说,你的设计是完全错误的。您应该使每个子块独立于时钟(使用always @(*)块而不是时钟驱动的块),然后在顶层模块中实例化所有这些块,每个块的输出驱动为Y_AddY_TolakY_DarabY_GateOrY_GateAnd信号。最后,在顶层你可以有一个时钟块,如:

always @(posedge clk)
begin:
  if (enb == 1'b1):
    case (S)
      3'b000: Y <= Y_Add;
      3'b001: Y <= Y_Tolak;
      [...]
    endcase
end

并确保Yreg,而不是wire。基本上,您将使用多路复用器驱动的值实现寄存器。