Verilog学习代码总结

01、8位加法器

功能代码

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

测试代码

`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、8位计数器

功能代码

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

测试代码

`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、二选一多路选择器

连续赋值方式

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

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

阻塞赋值方式

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、阻塞赋值实现双触发器

双触发器图


功能代码

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

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

测试代码

`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、四位移位寄存器

功能代码

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

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

测试代码

`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

模拟仿真

在这里插入图片描述

06、for循环七人表决器

功能代码

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

测试代码

`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

模拟仿真

在这里插入图片描述

07、32位整数循环

a、for实现

`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、while实现

`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、repeat实现

`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、模拟仿真

三者仿真结果相同

在这里插入图片描述

08、用持续赋值、task、function实现四选一

a、持续赋值

功能代码

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

测试代码

`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、task

`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、function

`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、模拟仿真

在这里插入图片描述

09、空调机

​ 设计一个空调机的控制机。温度传感器控制两个输入端temp_high和temp_low, 如果室内温度较高,则temp_high为’1’, 同时temp_low为’0’; 如果室内温度较低,则temp_high为’0’, 同时temp_ low为’1’; 如果室内温度正常,则temp_high为’0’, 同时temp_low为’0’。 根据输入端temp_high和temp_ _low的值来判断当前的状态是: 1.too_hot (太热) ; 2. too_cold (太冷) ; 3.just_right (正好),然后决定输出端heat和cool的值是’1’还是’0’,从而控制是制冷还是制热。

要求:

1.画出有限状态机,标明状态转换条件;

2.写出程序代码,标注说明和解释;

3.写出验证程序,对设计进行全面的验证。


状态转移图

在这里插入图片描述

源代码

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

测试代码

`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 

模拟仿真

在这里插入图片描述

10、交通灯

​ 设计一个交通灯控制器。一个十字交叉路口,东西方向为主干道(HighWay),南北方向为副干道(CountryWay) 。副干道车辆很少,因此在交叉路口处有车辆探测器(Sensor) ,可以判断副干道是否有车。如果没有车,则主干道始终绿灯(Green) ;如果副干道有车,则在主干道通行40秒后,主干道红灯(Red),而副干道绿灯,通行时间为20秒。这时无论副干道有无车,副干道都要红灯,而主干道绿灯。从绿灯到红灯的转换中间有4秒黄灯(Yellow) 。

要求:

1.画出有限状态机,标明状态转换条件;

2.写出程序代码,标注说明和解释;

3.写出验证程序,对设计进行全面的验证。


状态转换图

在这里插入图片描述

源代码

该程序源代码分为2子模块(计数器模块+交通灯模块)+顶模块

计数器模块
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
交通灯模块
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
顶层模块
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 

注意:当前代码中,默认了主干副干状态相互对应,red(主)-green(副),yellow(主)-yellow(副),green(主)-red(副)。

但实际上不是这样。

很多交通灯设计时,只有在red->green时需要穿插一个黄灯,正如题干最后一句。所以我这样的设计实际上是不符合题干要求的。

如果你想做一个更符合实际的,那么你需要再增加两个变量:cur_state2next_state2来保存副干状态。同时将状态机中的WAIT1状态删去,使得PASS直接指向STOP

测试代码

`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 

注意:交通灯模块中是用senor来判断是否在计时状态的。如果测试代码中,使senor=0时是在主干PASS的状态(senor=0意味着副干车没了,在主干PASS的状态下,副干原本的车突然没了?路口调头怕是来不及吧……所以本身算是一个伪命题——当然这排除了设备出故障情况),注意到交通灯模块并没有对计数器模块进行清零,所以下一次使senor=1时,主干通行时间可能会小于40S。

模拟仿真

在这里插入图片描述

11、基本门描述设计

利用Verilog基本门(门级)描述设计和验证如下图所示电路的结构化模型。并在设计的测试平台中分别使用模型名与端口名t_Combo_ str()和Combo_ str (Y,A,B,C,D)。

注意:该测试平台没有端口。

在这里插入图片描述


源代码

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

测试代码

`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

仿真结果

在这里插入图片描述

12、闹钟设计

在这里插入图片描述
在这里插入图片描述


源代码

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

测试代码

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

模拟仿真

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44856695/article/details/106103964