写在前面
- 这个专栏的内容记录的是Verilog题库刷题过程,附带RTL\TestBench,并进行
代码覆盖率收集
。- 该题库算是一个
Verilog宝藏刷题网站
了,提供在线仿真环境(题库),<刷题记录>专栏,持续打卡中…
一、题目
(1)题目描述
在某个module中包含了很多相似的连续赋值语句,请使用generate…for语句编写代码,替代该语句,要求不能改变原module的功能。使用Verilog HDL实现以上功能并编写testbench验证。
(2) 原程序
module template_module(
input [7:0] data_in,
output [7:0] data_out
);
assign data_out [0] = data_in [7];
assign data_out [1] = data_in [6];
assign data_out [2] = data_in [5];
assign data_out [3] = data_in [4];
assign data_out [4] = data_in [3];
assign data_out [5] = data_in [2];
assign data_out [6] = data_in [1];
assign data_out [7] = data_in [0];
endmodule
二、分析
1、generate语法结构
- 定义genvar,作为generate中的循环变量。
- generate语句中定义的for语句,必须要有begin。
- begin必须要有名称,也就是必须要有标签,因为标签会作为generate循环的实例名称。
2、generate:循环语句(loop)
//例子
'timescale 1 ns /1 ps
module nbic xor
#(parameter SIZE = 16)
(
input [SIZE-1 : 0] a,
input [SIZE-1 : 0] b,
output [SIZE-1 : 0] y
);
genvar gv_i; //这这类型的变量只能在generate循环语句中使用
generate
for (gv_i = o ; gv_i < SIZE ; gv_i = gv_i +1) begin : label
// label用来表示generate循环的实例名称
xor u_xor (y[gv_i] , a[gv_i] , b[gv_i]);
//实例化后的结果如下:
// label [0].u_xor (y[0] , a[0] , b[0]);
// label [1].u xor (y[1] , a[1] , b[1]);
// label [2],u_xor (y[2] , a[2] , b[2]);
// ... ...
// label [SIZE-1].u_xor (y[SIZE-1] , a[SIZE-1] , b[SIZE-2]);
//实例化后的层次路径如下:
// nbit xor.label [0].u_xor;
//... ...
//同理,还可以引用别的已经定义的module在generate语句中实例化
end
endgenerate
endmodule
3、generate:条件语句(conditional)
'timescale 1 ns /1 ps
module shift register
#(parameter BITS = 8)
(
input shift_in ,
inpuc clk ,
input resetn ,
output shift_out
);
wire [BITS-1 : 0] tq;
genvar gv_1; //这种类型的变量只能在generateim环语句中使用
// generate-condiciona1语句实质上是将条件语句放入到generate-for结构中
/*在该条件语句结构中,if语句的条件必须是静态的,这样的条件表达式
必须是由常数或者参数组成,也意味着在程序运行期间保持不变*/
generate
for (gv_1 =o : gv_i < BITS : gv_1 = gv_1 +1)begin : label
if (gvi == BITS-1) begin//此条件成立时, u0dff
dflip_flop uodff (
.d(serial_in) ,
.resetn (resetn) ,
.ck (clk) ,
.q(ta[gv_1])
);
end
else begin
if (gv_i == 0)begin //此条件成立时, uldff
dflip_flop uldff (
.d(tg[gv_1 + 1]) ,
.resetn (resetn) ,
.ck (clk) ,
.g(serial_out));
end
else begin//其他情况下, u2dff
dflip_flop u2dff (
.d(tq[gv_i + 1]) ,
.resetn (resetn) ,
.ck(clk) ,
.q(t[gv_11)
);
end
end
end
endgenerate
endmodule
generate允许对语句进行条件选择,即将条件选择加入到generate中的for循环中,只例化条件成立时对应的语句或者module。
4、generate:分支语句(case)
'timescale 1 ns /1 ps
module adder
# (parameter N =4)
(
input ci,
input [N-1 : 0] ao,
input [N-1 : 0] al,
output co,
output [N-1 : 0] sum
)//注意:未定义genvar变量//根据总线的位宽,调用相应的加法器
// 参数N在调用时可以重新定义,但是该值也是静态的,因为每次调用时N都是必须确定的
//调用不同位宽的加法器是根据不同的N来决定的
generate
case (N)
// 当N=1或者2时分别选用位宽为1位或2位的加法器
1: adder_lbit adder1 (co , sum, ao , al , ci); // 1位的加法器
2 : adder_2bie adder2 (co sum, ao, al , ci): // 2位的加法器1/默认的情况下选用位宽为N位的加法器
default : adder_cla # (N) adder3 (co , sum , ao , al , ci);
endcase
endgenerate
endmodule
三、RTL
module gen_for_module(
input [7:0] data_in ,
output [7:0] data_out
);
/*
assign data_out [0] = data_in [7];
assign data_out [1] = data_in [6];
assign data_out [2] = data_in [5];
assign data_out [3] = data_in [4];
assign data_out [4] = data_in [3];
assign data_out [5] = data_in [2];
assign data_out [6] = data_in [1];
assign data_out [7] = data_in [0];
*/
genvar gv_i;
generate
for(gv_i=0;gv_i<8;gv_i=gv_i+1)begin:gv_label
assign data_out[gv_i] = data_in[7-gv_i];
end
endgenerate
endmodule
四、Testbench
`timescale 1ps/1ps
module tb_gen_for_module;
reg [7:0] data_in ;
reg [7:0] data_out;
/*-----------------------------------------------\
-- --
\-----------------------------------------------*/
initial begin
repeat(10000)begin
d_case(data_in,{$random}%256);
#5000 ;
end
end
/*-----------------------------------------------\
-- --
\-----------------------------------------------*/
task d_case;
output [7:0] a;
input [7:0] b;
a = b;
endtask
/*-----------------------------------------------\
-- display --
\-----------------------------------------------*/
always @ (data_out)begin
if(data_out == {data_in[0],data_in[1],data_in[2],data_in[3],
data_in[4],data_in[5],data_in[6],data_in[7]})begin
end
else begin
$display($realtime,", error:gv_i = ;data_in = %d;data_out = %d",data_in,data_out);
end
end
gen_for_module u_gen_for_module(
.data_in (data_in ),
.data_out (data_out )
);
initial #60000000 $finish;
initial begin
$fsdbDumpfile("gen_for_module.fsdb");
$fsdbDumpvars ;
$fsdbDumpMDA ;
end
endmodule
五、结果分析
(1)TB结果
display无打印错误信息
(2)波形图
由上图可以知道,输出是输入的一个移位,使用generate-for简化代码的运行结果和原来一致。
(3)覆盖率
代码覆盖率100%
✍✍☛ 题库入口
经过一段时间的沉淀,发现入行IC行业,自己的底子还是很差,写的文章质量参差不齐,也没能解答大家的疑问。决定还是要实打实从基础学起,由浅入深。因此决定通过补充/完善基础知识的同时,通过题库刷题不断提高自己的设计水平,题库推荐给大家(点击直达),<题库记录>栏目不定期更新,欢迎前来讨论。
作者:xlinxdu
版权:本文版权归作者所有
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。