Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Verilog

Блок генерации Verilog

А generate Блок позволяет умножать экземпляры модулей или выполнять условное создание экземпляров любого модуля. Он предоставляет возможность построения дизайна на основе параметров Verilog. Эти операторы особенно удобны, когда одну и ту же операцию или экземпляр модуля необходимо повторить несколько раз или если определенный код должен быть условно включен на основе заданных параметров Verilog.

generate блок не может содержать порт, параметр, specparam декларации или specify блоки. Однако разрешены другие элементы модуля и другие блоки генерации. Все экземпляры генерации закодированы в module и между ключевыми словами generate и endgenerate .

Сгенерированные экземпляры могут иметь модули, непрерывные назначения, always или initial блоки и определяемые пользователем примитивы. Существует два типа конструкций generate — циклы и условные операторы.

Создать цикл

Полусумматор будет создан N раз в другом модуле дизайна верхнего уровня под названием my_design с использованием generate для конструкции цикла. Переменная цикла должна быть объявлена ​​с использованием ключевого слова genvar. который сообщает инструменту, что эта переменная должна быть специально использована во время разработки блока генерации.

  
  
// Design for a half-adder
module ha ( input   a, b,
            output  sum, cout);
 
  assign sum  = a ^ b;
  assign cout = a & b;
endmodule

// A top level design that contains N instances of half adder
module my_design 
	#(parameter N=4) 
		(	input [N-1:0] a, b,
			output [N-1:0] sum, cout);
			
	// Declare a temporary loop variable to be used during
	// generation and won't be available during simulation
	genvar i;
	
	// Generate for loop to instantiate N times
	generate 
		for (i = 0; i < N; i = i + 1) begin
          ha u0 (a[i], b[i], sum[i], cout[i]);
		end
	endgenerate
endmodule

  

Тестовый стенд

Параметр testbench используется для управления количеством экземпляров половинного сумматора в проекте. Когда N равно 2, my_design будет иметь два экземпляра половинного сумматора.

  
  
module tb;
	parameter N = 2;
  reg  [N-1:0] a, b;
  wire [N-1:0] sum, cout;
  
  // Instantiate top level design with N=2 so that it will have 2
  // separate instances of half adders and both are given two separate
  // inputs
  my_design #(.N(N)) md( .a(a), .b(b), .sum(sum), .cout(cout));
  
  initial begin
    a <= 0;
    b <= 0;
    
    $monitor ("a=0x%0h b=0x%0h sum=0x%0h cout=0x%0h", a, b, sum, cout);
    
    #10 a <= 'h2;
    		b <= 'h3;
    #20 b <= 'h4;
    #10 a <= 'h5;
  end
endmodule

  

a[0] и b[0] дают выходную сумму[0] и cout[0], а a[1] и b[1] дают выходную сумму[1] и cout[1].

Журнал моделирования
ncsim> run
a=0x0 b=0x0 sum=0x0 cout=0x0
a=0x2 b=0x3 sum=0x1 cout=0x2
a=0x2 b=0x0 sum=0x2 cout=0x0
a=0x1 b=0x0 sum=0x1 cout=0x0
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit

Обратите внимание, что усовершенствованный RTL действительно имеет два экземпляра половинного сумматора, сгенерированные generate. блокировать.

Создать, если

Ниже показан пример использования if else внутри generate конструкция для выбора между двумя различными реализациями мультиплексора. В первом дизайне используется assign оператор для реализации мультиплексора, в то время как во втором варианте используется case утверждение. Параметр с именем USE_CASE определяется в модуле дизайна верхнего уровня для выбора между двумя вариантами.

  
  
// Design #1: Multiplexer design uses an "assign" statement to assign 
// out signal 
module mux_assign ( input a, b, sel,
                   output out);
  assign out = sel ? a : b;
  
  // The initial display statement is used so that 
  // we know which design got instantiated from simulation
  // logs  
  initial
  	$display ("mux_assign is instantiated");
endmodule

// Design #2: Multiplexer design uses a "case" statement to drive
// out signal
module mux_case (input a, b, sel,
                 output reg out);
  always @ (a or b or sel) begin
  	case (sel)
    	0 : out = a;
   	 	1 : out = b;
  	endcase
  end
  
  // The initial display statement is used so that 
  // we know which design got instantiated from simulation
  // logs
  initial 
    $display ("mux_case is instantiated");
endmodule

// Top Level Design: Use a parameter to choose either one
module my_design (	input a, b, sel,
         			output out);
  parameter USE_CASE = 0;
  
  // Use a "generate" block to instantiate either mux_case
  // or mux_assign using an if else construct with generate
  generate
  	if (USE_CASE) 
      mux_case mc (.a(a), .b(b), .sel(sel), .out(out));
    else
      mux_assign ma (.a(a), .b(b), .sel(sel), .out(out));
  endgenerate
    
endmodule

  

Тестовый стенд

Testbench создает экземпляр модуля верхнего уровня my_design и устанавливает для параметра USE_CASE значение 1, чтобы он создавал экземпляр проекта, используя case. заявление.

  
  
module tb;
	// Declare testbench variables
  reg a, b, sel;
  wire out;
  integer i;
  
  // Instantiate top level design and set USE_CASE parameter to 1 so that
  // the design using case statement is instantiated
  my_design #(.USE_CASE(1)) u0 ( .a(a), .b(b), .sel(sel), .out(out));
  
  initial begin
  	// Initialize testbench variables
  	a <= 0;
    b <= 0;
    sel <= 0;
    
    // Assign random values to DUT inputs with some delay
    for (i = 0; i < 5; i = i + 1) begin
      #10 a <= $random;
      	  b <= $random;
          sel <= $random;
      $display ("i=%0d a=0x%0h b=0x%0h sel=0x%0h out=0x%0h", i, a, b, sel, out);
    end
  end
endmodule

  

Когда параметр USE_CASE равен 1, из журнала моделирования видно, что конструкция мультиплексора с использованием case создается экземпляр оператора. А когда USE_CASE равен нулю, схема мультиплексора с использованием assign создается экземпляр оператора. Это видно из оператора display, который печатается в журнале моделирования.

Журнал моделирования
// When USE_CASE = 1
ncsim> run
mux_case is instantiated
i=0 a=0x0 b=0x0 sel=0x0 out=0x0
i=1 a=0x0 b=0x1 sel=0x1 out=0x1
i=2 a=0x1 b=0x1 sel=0x1 out=0x1
i=3 a=0x1 b=0x0 sel=0x1 out=0x0
i=4 a=0x1 b=0x0 sel=0x1 out=0x0
ncsim: *W,RNQUIE: Simulation is complete.

// When USE_CASE = 0
ncsim> run
mux_assign is instantiated
i=0 a=0x0 b=0x0 sel=0x0 out=0x0
i=1 a=0x0 b=0x1 sel=0x1 out=0x0
i=2 a=0x1 b=0x1 sel=0x1 out=0x1
i=3 a=0x1 b=0x0 sel=0x1 out=0x1
i=4 a=0x1 b=0x0 sel=0x1 out=0x1
ncsim: *W,RNQUIE: Simulation is complete.

Создать обращение

Случай генерации позволяет создавать экземпляры модулей, начальных и всегда блоков в другом модуле на основе case выражение для выбора одного из множества вариантов.

  
  
// Design #1: Half adder
module ha (input a, b,
           output reg sum, cout);
  always @ (a or b)
  {cout, sum} = a + b;
  
  initial
    $display ("Half adder instantiation");
endmodule

// Design #2: Full adder
module fa (input a, b, cin,
           output reg sum, cout);
  always @ (a or b or cin)
  {cout, sum} = a + b + cin;
  
    initial
      $display ("Full adder instantiation");
endmodule

// Top level design: Choose between half adder and full adder
module my_adder (input a, b, cin,
                 output sum, cout);
  parameter ADDER_TYPE = 1;
  
  generate
    case(ADDER_TYPE)
      0 : ha u0 (.a(a), .b(b), .sum(sum), .cout(cout));
      1 : fa u1 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
    endcase
  endgenerate
endmodule

  

Тестовый стенд

  
  
module tb;
  reg a, b, cin;
  wire sum, cout;
  
  my_adder #(.ADDER_TYPE(0)) u0 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
  
  initial begin
    a <= 0;
    b <= 0;
    cin <= 0;
    
    $monitor("a=0x%0h b=0x%0h cin=0x%0h cout=0%0h sum=0x%0h",
             a, b, cin, cout, sum);
    
    for (int i = 0; i < 5; i = i + 1) begin
      #10 a <= $random;
      b <= $random;
      cin <= $random;
    end
  end
endmodule

  

Обратите внимание, что, поскольку используется половинный сумматор, cin не оказывает никакого влияния на выходную сумму и cout.

Журнал моделирования
ncsim> run
Half adder instantiation
a=0x0 b=0x0 cin=0x0 cout=00 sum=0x0
a=0x0 b=0x1 cin=0x1 cout=00 sum=0x1
a=0x1 b=0x1 cin=0x1 cout=01 sum=0x0
a=0x1 b=0x0 cin=0x1 cout=00 sum=0x1
ncsim: *W,RNQUIE: Simulation is complete.


Verilog

  1. Учебник Verilog
  2. Конкатенация Verilog
  3. Verilog - в ореховой скорлупе
  4. Верилог Задания
  5. Блокировка и неблокировка Verilog
  6. Верилог-функции
  7. Верилог Задача
  8. Генератор часов Verilog
  9. Математические функции Verilog
  10. Формат времени Verilog