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.
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
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
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.
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
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
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
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
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_state2
y next_state2
guardar el estado del líder adjunto. Al mismo tiempo, elimine el estado en la máquina de estados WAIT1
para que PASS
apunte 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 senor
utiliza para determinar si está en el estado de sincronización. Si en el código de prueba, la hora senor=0
está en PASS
el estado de la cajuela principal ( senor=0
lo que significa que el auto de la cajuela adjunta ya no está, en el PASS
estado 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=1
puede ser inferior a 40S.
Simulación
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.
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
12. Diseño de despertador
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