testbench的整理笔记
1 //设计的过程实际是从一种形式到另一种形式的转换,比如从设计规格到RTL代码,从RTL 2 3 //到门级网表,从门级网表到版图等。说的其实是设计的流程的转变,很有道理 4 //验证的目的就是保证每一步的设计转换过程中都准确无误。 5 //功能验证指的是从验证RTL代码是否符合原始的设计需求和规格。 6 //仿真:使用EDA工具通过对设计实际工作情况的模拟验证设计的正确性。 7 //testbench的使用首先知道它是什么个玩意?testbench是测试平台的意思,就是在仿真的时候testbench产生测试激励给待验证设计(DUT) 8 // 并检查DUT的输出是否与预期的一致,达到验证的目的 9 10 11 12 //编写仿真激励: 13 //1.使用initial和always语句 2.时钟复位的写法 14 15 //普通时钟信号 16 parameter period = 10; 17 reg clk; 18 initial 19 begin 20 clk = 0; 21 forever 22 #(period/2)clk = ~clk; 23 end 24 25 //或者 26 parameter period = 10; 27 reg clk; 28 initial 29 clk = 0; 30 always 31 #(period/2)clk = ~clk; 32 33 // 固定数目的时钟信号 34 parameter pulse = 4,period = 10; 35 reg clk; 36 initial 37 begin 38 clk=0; 39 repeat(pulse) 40 #(period/2)clk = ~clk; 41 end 42 43 //相移时钟信号 44 parameter HI_TIME = 5, 45 LO_TIME = 10, 46 PHASE_SHIFT = 2; 47 reg Absolute_clk; 48 wire Derived_clk; 49 always 50 begin 51 #HI_TIME Absolute_clk = 0; 52 #LO_TIME Absolute_clk = 1; 53 end 54 assign #PHASE_SHIFT Derived_clk = Absolute_clk; //相移为2 55 56 //异步复位信号 57 parameter period = 10; 58 reg rst_n; 59 initial 60 begin 61 rst_n = 1; 62 #period rst_n = 0; 63 #(5*period) rst_n = 1; 64 end 65 //同步复位信号和异步的有很大不同,见代码 66 initial 67 rst_n = 1; 68 @(negedge clk) 69 rst_n = 0; 70 # 30; 71 @(negedge clk) 72 rst_n = 1; 73 end 74 75 //产生值序列----------------------------------后续介绍 76 77 //利用系统函数和系统任务产生测试激励、显示调试信息、协助定位 78 //对于$readmemb系统任务,每个数字必须是二进制数字,对于$readmemh系统任务 79 //从文件里读出和写入数据 80 reg [7:0]datasource[0:47]; 81 $readmemh("Read_In_File.txt",datasource); //从已有的文件读入数据 82 //1.打开文件 83 integer file_id; 84 file_id = fopen("file_path/file_name"); 85 //2.写入文件 86 //$fmonitor只要有变化就一直记录 87 $fmonitor(file_id, "%format_char", parameter); 88 eg:$fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1); 89 //$fwrite需要触发条件才记录 90 $fwrite(file_id, "%format_char", parameter); 91 //$fdisplay需要触发条件才记录 92 $fdisplay(file_id, "%format_char", parameter); 93 $fstrobe(); 94 //3.读取文件 95 integer file_id; 96 file_id = $fread("file_path/file_name", "r"); 97 //4.关闭文件 98 $fclose(fjile_id); 99 //5.由文件设定存储器初值 100 //初始化数据为十六进制 101 $readmemh("file_name", memory_name"); 102 //初始化数据为二进制 103 $readmemb("file_name", memory_name"); 104 105 integer write_out_file; //定义一个整数的文件指针 106 write_out_file = $fopen("write_out_file.txt"); //打开文件 107 $fdisplay(write_out_file,"@%h\n%h",Mpi_add,data_in); //往文件中写入内容 108 $fclose(write_out_file); 109 110 //写并行激励 在仿真的时候的同一时刻启动多个任务,可以使用 fork join 111 112 //for语句实现遍历测试 113 //高级语句:force release,用的不多 114 //封装功能模块 115 /* 116 task 任务名称; 117 输入、输出声明; 118 语句; 119 endtask 120 121 //与task不同,function将会返回一个值 122 function [BITWIDHT-1:0]函数名称; 123 输出声明; 124 语句; 125 endfunction 126 */ 127 function [7:0]product; 128 input[3:0]sig_a; 129 input[3:0]sig_b; 130 begin 131 product = sig_a*sig_b; 132 end 133 endfunction 134 135 136 137 //搭建仿真环境 138 //确认仿真结果 139 140 141 //双向总线必须在顶层模块定义并且例化为三态信号,在顶层将双线总线分为输入和输出信号,然后根据需求传向不同的子模块 142 inout [7:0] data_bus; 143 wire [7:0] data_in;//双线信号的分裂 144 wire [7:0] data_out; 145 assign data_in = data_bus; 146 assign data_bus = ((!CS_)&&(!OE_))?data_out:8'bZZZZZZZZ; //三态总线的使能 147 // 在testbench测试平台上 148 reg [7:0] data_out; 149 reg [7:0] data_in; 150 tri [7:0] data_bus; 151 assign data_bus = ( oe )? data_out : 8'bz ; 152 153 // 结构化testbench思想:把不同操作的功能模块以task或者function的封装成一体作为总线功能模型(BFM) 154 // 而将要操作的数据作为参数去直接调用这种模型。 155 // 好处:BFM可重用; 156 // 结构清晰,易于设计,减小testbench设计工作量; 157 // 将testcase的抽象成都提高,无须关心底层细节; 158 // 适用于复杂的设计模块 159 160 // 总线功能模型(BFM)是一种将物理的接口时序操作转化为更高抽象层次接口的总线模型 161 // 测试套具就是harness 从系统测试角度说就是将被测模块固定(实例化)以便测试。 162 // 从验证verilog代码说就是将测试模块封装起来留出易用的的访问接口,以利于各种testcase调用、测试设计模块 163 // 单顶层的testbench只有一个顶层,harness的实例以及各种测试用例都在顶层中。 164 165 // 多顶层的testbench中通常有一个harness顶层,用来实例化设计模块,实例化BFM,以及提供一些基本的激励。而多个测试用例testcase都可以作为 166 // 顶层,不同的测试用例用来测试不同的特性或者边界条件,注意顶层之间没有端口映射,它们之间的访问是通过层次路径名方式访问。 167 168 // 设计一个testbench的基本思想和步骤:从需求(SPEC)规格到特性:从设计的规格提取设计的特性; 169 // 从特性到用例:根据设计特性,编写出相应的测试用例来检验该特性; 170 // 从用例到testbench:用例测试用例,就可以搭建测试平台 171 172 173 174 //从标志寄存器的低有效位开始查找第一个值为1 的位 175 reg[15:0]flag; 176 integer i; 177 initial 178 begin 179 flag = 16'b0010_0000_0000_0000; 180 i = 0; 181 begin:block1 182 while(i<16) 183 begin 184 if(flag[i]) 185 begin 186 $dispaly("number %d",i); 187 disable block1; 188 end 189 i = i+1; 190 end 191 end 192 end