例1.四位计数器(同步使能、异步复位)
// Module Name: counter_4bit // Description: 4bit异步复位同步使能二进制计数器 module counter_4bit( input clk, //系统时钟信号 input rst, //系统复位按键 input en, //计数器使能端 output reg [3:0]q //计数器计数值输出 ); //同步使能,异步复位 always@(posedge clk,posedge rst) if(rst) q <= 0; else if(en) q <= q + 1‘b1; //计数器加一 endmodule
testbench测试代码如下:
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Module Name: counter_4bit_tb // Description: 4bit计数器模块测试文件 ////////////////////////////////////////////////////////////////////////////////// `define clk_period 20 //宏定义时钟周期 module counter_4bit_tb(); reg clk; //用于产生时钟信号 reg rst; //用于产生复位信号 reg en; //用于产生使能信号 wire [3:0]q; //计数器计数值输出 //例化测试模块 counter_4bit counter_4bit_test( .clk(clk), //系统时钟信号 .rst(rst), //系统复位按键 .en(en), //计数器使能端 .q(q) //计数器计数值输出 ); //开始测试 //生成时钟信号 initial clk = 1; always #(`clk_period/2) clk = ~clk; //clk每5ns翻转一次,产生100M时钟信号 initial begin rst = 1; en = 0; #(`clk_period * 5 + 1 ); rst = 0; #(`clk_period * 5); en = 1; #(`clk_period *20); //因为4bit计数16个clk就清零,所以延时20个时钟周期 $stop; end endmodule
测试结果如下:

综合的电路图如下:

计数器是我们设计的第一个时序逻辑电路,也是最基本、最重要的时序逻辑电路,由图中可以看到一个计数器由加法器和D触发器组成;
特别要注意的一点,在用verilog描述计数寄存器加一的时候,我们没有先写一个加法器,然后例化调用,而是直接采用 q <= q + 1‘b1这样描述加法器,这点在综合出的电路图也可以看出,加法器不再是门电路的组合,而是用一个圆圈替代,这时,数字逻辑设计的思想就又抽象了一层,不再是门电路的组合,而是这些具有逻辑功能的小方块的组合,所以,抽象的思想在数字逻辑设计中至关重要;
在编写testbench仿真测试的时候,我们也不再像测试组合逻辑电路那样利用穷举法测试功能,而是利用时钟测试,比如测试4bit的加法器,一要测试它能不能在每个时钟沿加一,而要测试它计满时可不可以自动清零;所以,在测试时序逻辑电路的时候要准确把握clk时钟信号;
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Create Date: 2018/05/22 20:32:26 // Module Name: flashled // Description: 产生一个时钟信号,让LED灯按1hz的频率闪烁 ////////////////////////////////////////////////////////////////////////////////// //`define SIMULATION /*** 仿真时保留,板级验证时注释 ***/ module flashled( input clk, //时钟信号输入 input rst, //复位信号输入 input en, //使能信号输入 output [15:0]led //led信号输出 ); `ifdef SIMULATION //仿真情况下 parameter CNT_MAX = 26‘d49; `else //板级验证情况下 parameter CNT_MAX = 26‘d49_999_999; `endif reg [25:0]cnt; //最大计数值49_999_999 reg [15:0]led_clk; //输出驱动led的1hz信号 //计数器功能描述 always@(posedge clk,posedge rst) if(rst) cnt <= 0; else if(en)begin if(cnt == CNT_MAX) cnt <= 0; else cnt <= cnt + 1‘b1; end //产生1hz信号 always@(posedge clk,posedge rst) if(rst) led_clk <= 0; else if(cnt == CNT_MAX) led_clk <= ~led_clk; //每计满50_000_000个时钟周期(500ms),输出信号翻转一下 else led_clk <= led_clk; //经1hz信号输出到led assign led = led_clk; endmodule
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Module Name: flashled_tb // Description: flashled模块测试文件 ////////////////////////////////////////////////////////////////////////////////// `define clk_period 10 //100M时钟信号 module flashled_tb(); reg clk; //用于产生时钟信号 reg rst; //用于产生复位信号 reg en; //用于产生使能信号 wire [15:0]led; //观察led输出 //例化测试模块 flashled flashled_test( .clk(clk), //时钟信号输入 .rst(rst), //复位信号输入 .en(en), //使能信号输入 .led(led) //led信号输出 ); //产生时钟信号 initial clk = 1; always #(`clk_period/2) clk = ~clk; //开始测试 initial begin rst = 1; //复位; en = 0; #(`clk_period * 5); rst = 0; #(`clk_period * 5); en = 1; //使能 #(`clk_period * 50 * 5 ); //仿真情况下计数器每计50次翻转,所以应该延时50 * 5个时钟周次观察翻转情况 $stop; end endmodule
综合电路图如下:

在编写testbench测试分频器模块时,由于计数器计数值为49_999_999 ,所以花费长时间,因为只需要测试功能,看模块计到设定值后会不会翻转信号,所以这样就是在浪费时间;
为了加快仿真速度,可以在仿真时将最大值改为49,这样就非常快,为了方便,可以在verilog中使用条件编译:
`ifdef SIMULATION //仿真情况下 parameter CNT_MAX = 26‘d49; `else //板级验证情况下 parameter CNT_MAX = 26‘d49_999_999; `endif
//1.取某一位直接操作
wire [2:0]m;
assign m = out[5:3];
//2.循环移位(移位寄存器)
reg [7:0] shift_a;
always@(posedge clk)
shift_a <= {shifta[0],shift[7:1]};
reg [7:0] shift_a;
wire data;
always@(posedge clk)
shift_a <= {data,shift[7:1]};
reg [7:0] shift_a;
wire data;
always@(posedge clk)
shift_a <= {shift[7:1],data};
//3、拼接
wire [3:0]x;
wire [3:0]y;
wire [7:0]z;
wire [31:0]n;
assign z = {x,y};
assign n = {x,7{x}};
verilog设计代码如下(计数器部分和分频器相同):
//移位寄存器功能描述 always@(posedge clk,posedge rst) if(rst) led_temp <= 26‘h0001; else if(cnt == CNT_MAX) led_temp <= {led_temp[14:0],led_temp[15]}; //循环左移 else led_temp <= led_temp; //输出到led assign led = led_temp;
testbench仿真测试文件和分频器相同;
测试结果如下:


综合出的电路图如下:

原文:https://www.cnblogs.com/Mculover666/p/9077228.html