Resumen del código de aprendizaje de Verilog

01. sumador de 8 bits

Código de función

module  adder_8 ( cout,sum,a,b,cin ); 
input [7:0]  a,b; 
input    cin; 
output   cout; 
output [7:0]  sum;

assign {cout,sum} = a + b + cin; 
endmodule

código de prueba

`timescale 1ns/1ns
module adder_8_test; 
reg [7:0]a, b; 
reg cin; 
wire [7:0] sum; 
wire cout; 
parameter INTERVAL;

adder_8 a1(.cout(cout), .sum(sum), .a(a), .b(b), .cin(cin));

initial
begin
  #INTERVAL {a,b,cin} = 17'b0000_0000_0000_0000_0;
  #INTERVAL {a,b,cin} = 17'b1101_1011_0010_0011_0;
  #INTERVAL {a,b,cin} = 17'b1111_0000_0000_1111_1;
  #INTERVAL {a,b,cin} = 17'b1001_0100_1001_0011_1;
end

endmodule

02. Contador de 8 bits

Código de función

module counter(out,clk,enable,rst);
output[7:0]  out;
input clk, rst, enable;
reg[7:0] out;
always @ (posedge clk) begin
  if (rst) begin
    out <= 8'b0;
  end else if (enable) begin
    out <= out + 1;
  end
end
endmodule

código de prueba

`timescale 1ns/1ns
module counter_tb; 
reg clk, enable, rst; 
wire [7:0] out; 
parameter INTERVAL = 10;

counter c1(.out(out), .clk(clk), .enable(enable), .rst(rst));
 
initial begin
  enable = 1;
  clk = 0;
  forever #(INTERVAL/2) clk = ~clk;
end

initial begin
  rst = 1;
  #INTERVAL rst = 0;
  #(200*INTERVAL) $finish;
end

endmodule

03. Multiplexor dos a uno

Método de asignación continua

module onInTwo(a,b,s,d);
  input a,b,s;
  output d;

  assign d = (s == 0)?a:b;
endmodule

método de asignación de bloqueo

module onInTwo2(out,d,a,s);
input a,b,s;
output out;

always @(*)begin
  if (s==0) begin
    out = a;
  end else begin
    out = b;
  end
end
endmodule

04. Asignación de bloqueo para implementar activadores dobles.

Diagrama de doble flip-flop


Código de función

module Dflip(output c,input a,input clk,);
reg b,c;

always @(posedge clk)begin
  c=b;
  b=a;
end
endmodule

código de prueba

`timescale  1ns / 1ns

module tb_Dflip; 
parameter INTERVAL = 10; 
reg a = 0,clk=0; 
wire c; 
initial begin 
  forever #(INTERVAL/2)  clk = ~clk;
end 
initial begin
  forever #(INTERVAL)  a = ~a;
end
Dflip d1(.c (c),.a (a), .clk (clk));

endmodule

05. Registro de desplazamiento de cuatro bits

Código de función

module register(out,clk,in);
input clk,in;
output [3:0]  out;

always @(posedge clk) begin
  out    = (out<<1);
  out[0] = in;
end
endmodule

código de prueba

`timescale 1ns/1ns
module tb_register;
wire [3:0] out;
parameter INTERVAL = 10;
reg in, clk;
initial forever #(INTERVAL/2) clk = ~clk;
initial forever #INTERVAL in = ~in;
initial begin 
  clk = 1;
  in = 1;
end

register r1(.out(out),.clk(clk), .in(in));

initial #(INTERVAL*100) $finish;

endmodule

Simulación

Insertar descripción de la imagen aquí

06. Dispositivo de votación para siete personas en bucle For

Código de función

module vote_7(output pass,input [6:0] vote);
integer i;
reg[2:0] vote_count;
always@(vote)begin
  vote_count=0;
  for(i = 0;i<7;i = i+1) begin
    if (vote[i])
      vote_count = vote_count+1;
  end
end
assign pass = (vote_count>3) ? 1 : 0;
endmodule

código de prueba

`timescale 1ns/1ns
module tb_vote_7;
reg[6:0] vote;
wire pass;
parameter INTERVAL = 10;

initial begin 
  #INTERVAL vote = 7'b1001010;
  #INTERVAL vote = 7'b0101101;
  #INTERVAL vote = 7'b1001011;
  #INTERVAL vote = 7'b1011111;
  #INTERVAL vote = 7'b0001010;
  #INTERVAL vote = 7'b1000011;
  #INTERVAL vote = 7'b1011000;
  #INTERVAL vote = 7'b1101011;
end

vote_7 v1(.pass(pass),.vote(vote));
endmodule

Simulación

Insertar descripción de la imagen aquí

07. Bucle entero de 32 bits

a. para la implementación

`timescale 1ns/1ns
module tb_circle_32;
reg [31:0] num;
reg temp;
integer i;
initial begin
  #10
  for(i=0;i<32;i=i+1) begin
  #10
    temp = num[31];
    num = (num<<1);
    num[0] =temp;
  end
end
initial
  num = 32'b1011_0101_1001_0100_1100_0110_1011_1101;
initial #500 $finish;
endmodule

B. durante la implementación

`timescale 1ns/1ns
module tb_circle_32;
reg [31:0] num;
reg temp;
integer i;
initial begin
  #10
  i=0;
  while(i<32) begin
    #10
    temp = num[31];
    num = (num<<1);
    num[0] =temp;
    i=i+1;
  end
end
initial
  num = 32'b1011_0101_1001_0100_1100_0110_1011_1101;
initial #500 $finish;
endmodule

C. Repetir la implementación

`timescale 1ns/1ns
module tb_circle_32;
reg [31:0] num;
reg temp;
initial begin
  #10
  repeat(32) begin
    #10
    temp = num[31];
    num = (num<<1);
    num[0] =temp;
  end
end
initial num = 32'b1011_0101_1001_0100_1100_0110_1011_1101;
initial #700 $finish;
endmodule

D. Simulación

Los resultados de la simulación de los tres son los mismos.

Insertar descripción de la imagen aquí

08. Utilice asignación, tarea y función continuas para realizar una de las cuatro opciones.

a. Asignación continua

Código de función

module oneInFour(y,a,b,enable,d0,d1,d2,d3);
input a,b,enable,d0,d1,d2,d3;
output y;

assign y = !enable&&((!a && !b && d0) || (!a && b && d1) || (a && !b && d2) || (a && b && d3));
endmodule

código de prueba

`timescale 10ns/10ns
module tb_oneInFour;
reg a,b,enable,d0,d1,d2,d3;
wire y;
    
initial begin
  enable  = 0;
  {d0,d1,d2,d3} = 4'b0110;
end
    
initial begin
  {a,b} = 2'b00
  #10 {a,b} = 2'b01;
  #10 {a,b} = 2'b10;
  #10 {a,b} = 2'b11;
  #10 $finish;
end

oneInFour u1(.y(y),.a(a),.b(b),.enable(enable),.d0(d0),.d1(d1),.d2(d2),.d3(d3));
    
endmodule

b, tarea

`timescale 10ns/10ns
module tb_oneInFour_task;
reg a,b,enable,d0,d1,d2,d3,y;

initial begin
  enable  = 0;
  {d0,d1,d2,d3} = 4'b0110;
end
    
initial begin
  {a,b} = 2'b00
  #10 {a,b} = 2'b01;
  #10 {a,b} = 2'b10;
  #10 {a,b} = 2'b11;
  #10 $finish;
end

always @(a or b or enable or d0 or d1 or d2 or d3) begin
    selectOne(y,a,b,enable,d0,d1,d2,d3);
end
    
task selectOne;
  input a,b,enable,d0,d1,d2,d3;
  output y;
  begin
    y = !enable&&((!a && !b && d0) || (!a && b && d1) || (a && !b && d2) || (a && b && d3));
  end
endtask

endmodule

c、función

`timescale 10ns/10ns
module tb_oneInFour_fun;
reg a,b,enable,d0,d1,d2,d3, y;

function selectOne;
  input a,b,enable,d0,d1,d2,d3;
  begin
    selectOne = !enable&&((!a && !b && d0) || (!a && b && d1) || (a && !b && d2) || (a && b && d3));        
  end
endfunction

initial begin
  enable  = 0;
  {d0,d1,d2,d3} = 4'b0110;
end
    
initial begin
  {a,b} = 2'b00
  #10 {a,b} = 2'b01;
  #10 {a,b} = 2'b10;
  #10 {a,b} = 2'b11;
  #10 $finish;
end

always @(a or b or enable or d0 or d1 or d2 or d3) begin
  y = selectOne(a,b,enable,d0,d1,d2,d3);
end
    
endmodule

D. Simulación

Insertar descripción de la imagen aquí

09. Aire acondicionado

​ Diseñar una unidad de control para un aire acondicionado. El sensor de temperatura controla los dos terminales de entrada temp_high y temp_low. Si la temperatura interior es alta, temp_high es '1' y temp_low es '0'; si la temperatura interior es baja, temp_high es '0' y temp_low es '1'. '; Si la temperatura interior es normal, temp_high es '0' y temp_low es '0'. De acuerdo con los valores de los terminales de entrada temp_high y temp_ _low, determine el estado actual: 1.too_hot (demasiado caliente); 2. too_cold (demasiado frío); 3.just_right (perfecto), y luego determine el valores de los terminales de salida calor y frío 1' o '0' para controlar si está enfriando o calentando.

Requerir:

1. Dibujar una máquina de estados finitos e indicar las condiciones de transición de estado;

2. Escribir código de programa, marcar instrucciones y explicaciones;

3. Escriba un programa de verificación para verificar completamente el diseño.


diagrama de transición de estado

Insertar descripción de la imagen aquí

código fuente

module air(clk,rst,temp_high,temp_low,heat,cool);
  input clk,rst,temp_high,temp_low;
  output heat,cool;
  reg heat,cool;
  reg [1:0] cur_state,next_state;
  //定义三个状态
  parameter TOO_HIGH = 2'b10,
            JUST_RIGHT = 2'b00,
            TOO_LOW = 2'b01;

  //时序  设置当前状态为预设的下一状态或初始
  always @(posedge clk or posedge rst) begin
    if(rst)begin
      //重设置零
      cur_state <= JUST_RIGHT;
    end else begin
      cur_state <= next_state;
    end
  end

  //根据当前状态决定输出
  always @(cur_state) begin
    case (cur_state)
      TOO_HIGH: begin
        {heat,cool} = 2'b01;
      end 
      JUST_RIGHT: begin
        {heat,cool} = 2'b00;
      end 
      TOO_LOW: begin
        {heat,cool} = 2'b10;
      end 
      default: begin
        {heat,cool} = 2'b00;
      end 
    endcase
  end

  //根据输入决定下一预设状态
  always @(cur_state or temp_high or temp_low or rst) begin
    if(rst)
        next_state <= JUST_RIGHT;
    else begin
	    case (cur_state)
	      TOO_HIGH: begin
	        next_state = (temp_high == 1)?TOO_HIGH:JUST_RIGHT;
	      end
	      JUST_RIGHT: begin
	        if (temp_high == 1 && temp_low == 0) begin
	          next_state = TOO_HIGH;
	        end else if (temp_high == 0 && temp_low == 1) begin
	          next_state = TOO_LOW;
	        end else begin
	          next_state = JUST_RIGHT;
	        end
	      end 
	      TOO_LOW: begin
	        next_state = (temp_low == 1)?TOO_LOW:JUST_RIGHT;
	      end 
	      default: begin
	        next_state = JUST_RIGHT;
	      end 
	    endcase
    end
  end
endmodule

código de prueba

`timescale 1ns/1ns
module tb_air;
reg clk,rst,temp_high,temp_low;
wire heat,cool;
parameter PERIOD = 10;
parameter CHANGE_PERIOD = 4*PERIOD;

//初始化各值
initial begin
    clk = 1'b0;
    rst = 1'b0;
    temp_high = 1'b0;
    temp_low = 1'b0;
end

//设定时钟周期
initial 
  forever #(PERIOD/2) clk = ~clk;

//重置模块
initial begin
  #PERIOD rst = 1;
  #PERIOD rst = 0;
end

initial begin
  //测试JUST_RIGHT状态下输入改变
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b11;
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b00;
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b01;
  //转入TOO_LOW,测试TOO_LOW状态下输入改变
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b01;
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b11;
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b10;
  //重新转入JUST_RIGHT
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b10;
  //转入TOO_HIGH,测试TOO_HIGH状态下输入改变
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b11;
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b10;
  #CHANGE_PERIOD {temp_high,temp_low} = 2'b00;
  #CHANGE_PERIOD $finish;
end

//实例化模块
air i1(clk,rst,temp_high,temp_low,heat,cool);

endmodule //tb_air 

Simulación

Insertar descripción de la imagen aquí

10. Semáforos

​ Diseñar un controlador de semáforo. En una intersección, la dirección este-oeste es la carretera principal (HighWay) y la dirección norte-sur es la carretera secundaria (CountryWay). Hay muy pocos vehículos en la vía arterial secundaria, por lo que hay un detector de vehículos (Sensor) en la intersección para determinar si hay automóviles en la vía arterial secundaria. Si no hay autos, la vía principal siempre tendrá luz verde; si hay autos en la vía secundaria, la vía principal tendrá luz roja (Red) luego de 40 segundos de paso por la vía principal, mientras que la vía secundaria tendrá luz verde, y el tiempo de paso será de 20 segundos. En este momento, independientemente de si hay automóviles en la vía subtroncal, la vía subtroncal tendrá luz roja, mientras que la vía principal tendrá luz verde. Hay una luz amarilla de 4 segundos en la transición de la luz verde a la luz roja.

Requerir:

1. Dibujar una máquina de estados finitos e indicar las condiciones de transición de estado;

2. Escribir código de programa, marcar instrucciones y explicaciones;

3. Escriba un programa de verificación para verificar completamente el diseño.


Diagrama de transición de estado

Insertar descripción de la imagen aquí

código fuente

El código fuente del programa se divide en 2 submódulos (módulo contador + módulo de semáforo) + módulo superior

Módulo contador
module counter(out,clk,enable,rst);
output[6:0]  out;
input clk, rst,enable;
reg[6:0] out;
    
always @ (posedge rst or posedge clk) begin
  if (rst) begin
    out <= 8'b0;
  end else if (enable) begin
    out <= (out + 1)%69;
  end
end

endmodule
módulo de semáforo
module light(highWay,countryWay,counter_enable,clk,rst,senor,count);
input clk,rst,senor;
input [6:0] count;
output counter_enable;
output [1:0] highWay,countryWay;
reg counter_enable;
reg [1:0] highWay,countryWay;
//标志计数状态
wire [6:0] count;

//主干状态,副干状态与之对应
reg [1:0] cur_state,next_state;
//灯输出结果常量
parameter GREEN = 2'b00,
          YELLOW = 2'b01,
          RED = 2'b11;
//状态常量
parameter PASS = 2'b00,
          WAIT1 = 2'b01,
          WAIT2 = 2'b10,
          STOP = 2'b11;          

//根据下一状态或重置改变现在状态
always @(posedge rst or posedge clk) begin
  if(rst) begin
    cur_state <= PASS;
  end else begin
    cur_state <= next_state;
  end
end

//不同状态不同输出
always @(cur_state) begin
  case (cur_state)
    PASS:begin
      highWay = GREEN;
      countryWay = RED;
    end 
    WAIT1:begin
      highWay = YELLOW;
      countryWay = YELLOW;
    end
    WAIT2:begin
      highWay = YELLOW;
      countryWay = YELLOW;
    end
    STOP:begin
      highWay = RED;
      countryWay = GREEN;
    end
    default: begin
      highWay = GREEN;
      countryWay = RED;
    end 
  endcase
end

//根据输入改变下一预设状态
always @(senor or count or rst) begin
  if(rst) begin
    next_state <= PASS;
    counter_enable <= 0;
  end else begin
  next_state = PASS;
  case (cur_state)
    PASS:begin
      if (senor) begin
        if (count==40) begin
          next_state = WAIT1;
        end
        counter_enable = 1;
      end else begin
        counter_enable = 0;
      end
    end
    WAIT1:begin
      next_state = (count==44)?STOP:WAIT1;
    end
    WAIT2:begin
      next_state = (count==68)?PASS:WAIT2;
    end
    STOP:begin
      next_state = (count==64)?WAIT2:STOP;
    end
  endcase
end

endmodule
módulo de nivel superior
module top(highWay,countryWay,clk,rst,senor);
input clk,rst,senor;
output [1:0] highWay,countryWay;
wire counter_enable;
wire [6:0] count;

light i1(.highWay(highWay),.countryWay(countryWay),
  .counter_enable(counter_enable),
  .clk(clk),.rst(rst),
  .senor(senor),.count(count));

counter c1(.out(count),.clk(clk),
  .enable(counter_enable),.rst(rst));

endmodule 

Nota: En el código actual, los estados de la troncal y la troncal adjunta se corresponden entre sí de forma predeterminada, rojo (principal)-verde (suplente), amarillo (principal)-amarillo (suplente), verde (principal)-rojo (suplente).

Pero ese no es el caso.

Al diseñar muchos semáforos, solo es necesario intercalar una luz amarilla cuando está roja-> verde, al igual que la última oración de la pregunta. Por lo tanto, mi diseño en realidad no cumple con los requisitos de la pregunta.

Si desea hacerlo más realista, entonces necesita agregar dos variables más: cur_state2y next_state2guardar el estado del líder adjunto. Al mismo tiempo, elimine el estado en la máquina de estados WAIT1para que PASSapunte directamente STOP.

código de prueba

`timescale 1ns/1ns
module tb_light;
reg clk,rst,senor;
wire [1:0] highWay,countryWay;
parameter INTERVAL = 10;

//初始化各值
initial begin
    clk = 1'b0;
    rst = 1'b0;
    senor = 1'b0;
end

//设定时钟周期
initial 
  forever #(INTERVAL/2) clk = ~clk;

//重置模块
initial begin
  #INTERVAL rst = 1;
  #INTERVAL rst = 0;
end

initial begin
  //测试副干有车情况
  #(5*INTERVAL) senor = 1'b1;
  //测试副干无车情况
  #(60*INTERVAL) senor = 1'b0;
  #(100*INTERVAL) $finish;
end

//实例化模块
top t1(highWay,countryWay,clk,rst,senor);

endmodule 

Nota: El módulo de semáforo se senorutiliza para determinar si está en el estado de sincronización. Si en el código de prueba, la hora senor=0está en PASSel estado de la cajuela principal ( senor=0lo que significa que el auto de la cajuela adjunta ya no está, en el PASSestado de la cajuela, ¿el auto original de la cajuela auxiliar desaparece repentinamente? Puede que sea demasiado tarde para dar la vuelta en la intersección... por lo que es una proposición falsa en sí misma (por supuesto, esto excluye la falla del equipo). Tenga en cuenta que el módulo de semáforo no borra el módulo de contador, por lo que la próxima vez que se use, el tiempo de tráfico troncal senor=1puede ser inferior a 40S.

Simulación

Insertar descripción de la imagen aquí

11. Diseño de descripción básica de puerta.

Las puertas básicas de Verilog (nivel de puerta) se utilizan para describir el diseño y la verificación del modelo estructurado del circuito que se muestra en la siguiente figura. Y utilice el nombre del modelo y el nombre del puerto t_Combo_ str() y Combo_ str (Y,A,B,C,D) respectivamente en la plataforma de prueba diseñada.

NOTA: Esta plataforma de prueba no tiene puertos.

Insertar descripción de la imagen aquí


código fuente

module Combo_str(Y,A,B,C,D);
input A,B,C,D;
output Y;
wire D_bar,A_D,A_D_bar,B_C_D_bar;

not n1(D_bar,D),n2(A_D_bar,A_D);
or o1(A_D,A,D);
and a1(B_C_D_bar,D_bar,B,C),a2(Y,A_D_bar,B_C_D_bar);

endmodule

código de prueba

`timescale 10ns/1ns
module t_Combo_str;
parameter INTERVAL = 10; 
reg A,B,C,D;
wire Y;

initial begin
  #INTERVAL {A,B,C,D} = 4'b0000;
  #INTERVAL {A,B,C,D} = 4'b0001;
  #INTERVAL {A,B,C,D} = 4'b0010;
  #INTERVAL {A,B,C,D} = 4'b0011;

  #INTERVAL {A,B,C,D} = 4'b0100;
  #INTERVAL {A,B,C,D} = 4'b0101;
  #INTERVAL {A,B,C,D} = 4'b0110;
  #INTERVAL {A,B,C,D} = 4'b0111;

  #INTERVAL {A,B,C,D} = 4'b1000;
  #INTERVAL {A,B,C,D} = 4'b1001;
  #INTERVAL {A,B,C,D} = 4'b1010;
  #INTERVAL {A,B,C,D} = 4'b1011;

  #INTERVAL {A,B,C,D} = 4'b1100;
  #INTERVAL {A,B,C,D} = 4'b1101;
  #INTERVAL {A,B,C,D} = 4'b1110;
  #INTERVAL {A,B,C,D} = 4'b1111;
end

Combo_str c1(Y,A,B,C,D);

endmodule

Resultados de la simulación

Insertar descripción de la imagen aquí

12. Diseño de despertador

Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí


código fuente

module clock(out,alarm,work,clk,rst);
input alarm,work,clk,rst;
output out;
reg out;
reg [2:0] cur_state,next_state;
parameter ASLEEP = 3'b001,
          AWAKE = 3'b010,
          RISE = 3'b100;

//更改当前状态
always @(posedge clk or posedge rst) begin
  if (rst) begin
    cur_state <= ASLEEP;
  end else begin
    cur_state <= next_state;
  end
end

//输出
always @(cur_state or alarm) begin
  if (cur_state == AWAKE) begin
    out = 0;
  end else begin
    out = alarm?1:0;
  end
end

//修改下一状态
always @(cur_state or alarm or work or rst) begin
  if(rst)
      next_state <= ASLEEP;
  else begin
	  next_state = RISE;
	  case (cur_state)
	    ASLEEP: begin 
	      next_state = alarm?AWAKE:ASLEEP;
	    end
	    AWAKE: begin 
	      if (alarm) begin
	        next_state = AWAKE;
	      end else begin
	        next_state = work?RISE:ASLEEP;
	      end
	    end
	    RISE: begin 
	      next_state = RISE;
	    end
	  endcase
  end
end

endmodule

código de prueba

module tb_clock;
reg alarm,work,clk,rst;
wire out;
parameter INTERVAL = 10;

initial begin
  alarm = 0;
  work = 0;
end

initial begin
  clk = 0;
  forever #(INTERVAL/2) clk = ~clk;
end

initial begin
  //测试非工作日
  #INTERVAL rst = 1;
  #INTERVAL rst = 0;
  #(INTERVAL*2) alarm = 1;
  #(INTERVAL*2) alarm = 0;
  //测试工作日
  #INTERVAL work = 1;
  #INTERVAL rst = 1;
  #INTERVAL rst = 0;
  #(INTERVAL*2) alarm = 1;
  #(INTERVAL*2) alarm = 0;
  #INTERVAL $finish;
end

clock c(.out(out),.alarm(alarm),.work(work),.clk(clk),.rst(rst));

endmodule

Simulación

Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_44856695/article/details/106103964
Recomendado
Clasificación