写在前面
- 这个专栏的内容记录的是牛客的Verilog题库刷题,附带RTL\TestBench,并进行
覆盖率收集
。- 牛客算是一个
Verilog宝藏刷题网站
了,网站提供在线仿真环境,不用自己找题(点击直达),<刷题记录>专栏,持续打卡中…
现在输入了一个压缩的16位数据,其实际上包含了四个数据[3:0][7:4][11:8][15:12],现在请按照sel选择输出四个数据的相加结果,并输出valid_out信号(在不输出时候拉低)
sel | out | validout |
---|---|---|
0: | 不输出且只有此时的输入有效 | 0 |
1 | 输出[3:0]+[7:4] | 1 |
2 | 输出[3:0]+[11:8] | 1 |
3 | 输出[3:0]+[15:12] | 1 |
信号 | 方向 | 类型 | 位宽 | 描述 |
---|---|---|---|---|
clk | input | wire | 1 | 时钟,周期为5ns |
rst | input | wire | 1 | 同步复位,低电平有效 |
d | input | wire | 16 | 输入的16bit数据 |
validout | output | reg | 1 | 有效输出时为1,否则为0 |
out | output | reg | 5 | 输出结果 |
题意可知,模块采用同步复位且复位信号在低电平有效;可以使用时序逻辑对输入数据d进行锁存到data_buff;输出信号out和validout可使用组合逻辑输出,输出信号根据sel的变化进行变化。
module data_cal(
input clk ,
input rst ,
input [15:0] d ,
input [1 :0] sel ,
output reg [4:0] out ,
output reg validout
);
reg [15:0] data_buff;
//*************code***********//
always @ (posedge clk) begin
if (!rst) begin
data_buff <= 16'b0;
out <= 5'b0;
validout <= 1'b0;
end
else begin
data_buff <= d;
end
end
always @ (*) begin
if(sel)begin
validout = 1'b1;
end
else begin
validout = 1'b0;
end
end
always @ (*) begin
case(sel)
2'd0:out = 5'b0;
2'd1:out = data_buff[3:0] + data_buff[7 :4 ];
2'd2:out = data_buff[3:0] + data_buff[11:8 ];
2'd3:out = data_buff[3:0] + data_buff[15:12];
default:out = 5'b0;
endcase
end
//*************code***********//
endmodule
`timescale 1ps/1ps
module tb_data_cal;
reg clk ;
reg rst ;
reg [15:0] d ;
reg [ 4:0] sel ;
wire [4 :0] out ;
wire validout ;
//-- debug signal
/*-----------------------------------------------\
-- --
\-----------------------------------------------*/
initial begin
clk = 1 ;
rst = 1 ;
d = 16'd0 ;
#1000 rst = 0;
#4001 rst = 1;
d_case(d,16'd0 );
#5000 d_case(d,16'b1000_0100_0010_0001);
#20000 d_case(d,16'b1000_0100_0010_0011);
#25000 d_case(d,16'b1000_0100_0010_0111);
#5000 d_case(d,16'b1000_0100_0010_1111);
#5000 d_case(d,16'b1000_0100_0011_1111);
#5000 d_case(d,16'b1000_0100_0111_1111);
#5000 d_case(d,16'b1000_0100_1111_1111);
#5000 d_case(d,16'b1000_0101_1111_1111);
#5000 d_case(d,16'b1000_0111_1111_1111);
#5000 d_case(d,16'b1000_1111_1111_1111);
#5000 d_case(d,16'b1001_1111_1111_1111);
#5000 d_case(d,16'b1011_1111_1111_1111);
#5000 d_case(d,16'b1111_1111_1111_1111);
#20000 ;
repeat(10000)begin
#5000 d_case(d,{$random}%8'hFF);
end
end
/*-----------------------------------------------\
-- sigal var T*5000ps --
\-----------------------------------------------*/
initial begin
sel_case(sel,0);
#15000 sel_case(sel,2);
#15000 sel_case(sel,2);
#15000 sel_case(sel,1);
#5000 sel_case(sel,0);
#25000 sel_case(sel,3);
repeat(10000)begin
#5000 sel_case(sel,{$random}%4);
end
end
/*-----------------------------------------------\
-- task of d_case and sel_case --
\-----------------------------------------------*/
task d_case;
output [15:0] a;
input [15:0] b;
a = b;
endtask
task sel_case;
output [1:0] s ;
input [1:0] b ;
begin
s = b;
end
endtask
/*-----------------------------------------------\
-- clock period is 5ns --
\-----------------------------------------------*/
always begin
#2500 clk = ~clk;
end
/*-----------------------------------------------\
-- display --
\-----------------------------------------------*/
always @ (data_cal.data_buff)begin
if(sel == 2'd0)begin
if((out != 0) || (validout != 0))begin
$display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff,out,validout);
end
else begin
end
end
else if(sel == 2'd1) begin
if((out != data_cal.data_buff[3:0] + data_cal.data_buff[7:4]) || (validout != 1'b1))begin
$display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff[3:0] + data_cal.data_buff[7:4],out,validout);
end
else begin
end
end
else if(sel == 2'd2) begin
if((out != data_cal.data_buff[3:0] + data_cal.data_buff[11:8]) || (validout != 1'b1))begin
$display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff[3:0] + data_cal.data_buff[11:8],out,validout);
end
else begin
end
end
else if(sel == 2'd3) begin
if((out != data_cal.data_buff[3:0] + data_cal.data_buff[15:12]) || (validout != 1'b1))begin
$display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff[3:0] + data_cal.data_buff[15:12],out,validout);
end
else begin
end
end
end
data_cal u_data_cal(
.clk (clk ),
.rst (rst ),
.d (d ),
.out (out ),
.sel (sel ),
.validout (validout)
);
initial #60000000 $finish;
initial begin
$fsdbDumpfile("data_cal.fsdb");
$fsdbDumpvars ;
$fsdbDumpMDA ;
end
endmodule
由波形图可tb可以确定,输出符合预期结果
可以看到总覆盖率只有93.92%,受行覆盖率和分支覆盖率的影响。查看信息可以看到主要是case语句的default语句没有被执行到。
✍✍☛ 题库入口
经过一段时间的沉淀,发现入行IC行业,自己的底子还是很差,写的文章质量参差不齐,也没能解答大家的疑问。决定还是要实打实从基础学起,由浅入深。因此决定通过补充/完善基础知识的同时,通过题库刷题不断提高自己的设计水平,题库推荐给大家(点击直达),<题库记录>栏目不定期更新,欢迎前来讨论。
作者:xlinxdu
版权:本文版权归作者所有
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。