VL9 使用子模块实现三输入数的大小比较

发布于:2022-12-02 ⋅ 阅读:(393) ⋅ 点赞:(0)

写在前面

  1. 这个专栏的内容记录的是Verilog题库刷题过程,附带RTL\TestBench,并进行代码覆盖率收集
  2. 该题库算是一个Verilog宝藏刷题网站了,提供在线仿真环境(题库),<刷题记录>专栏,持续打卡中…


一、题目

(1)题目描述

   在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。

   请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。


(2) 状态转换

对于子模块

条件 子模块输出
a > b b
a = b a,b都行
a < b a
其他(如出现X或者Z) z

(3)信号示意图

在这里插入图片描述


(4)端口描述

信号 方向 类型 位宽 描述
clk input wire 1bit 时钟,时钟周期为5ns
rst_n input wire 1bit 复位信号,异步下降沿有效
a input wire 8bit 输入的数据data_a
b input wire 8bit 输入的数据data_b
c input wire 8bit 输入的数据data_c
d output reg 8bit 输出a,b,c三者中的最小值

二、分析

  设计一个二输入比较器子模块,主模块通过调用一个子模块,子模块输出值直接和第三个值比较大小,最后输出最小值。如果调用两个子模块进行比较,会多消耗一个比较器资源。

在这里插入图片描述


三、RTL

1、top module

module main_mod
(
//-- system signal
  input            clk  ,
  input            rst_n,

//-- input signal
  input      [7:0] a,
  input      [7:0] b,
  input      [7:0] c,

//-- 
  output reg [7:0] d
);

wire [7:0] data0;
reg  [7:0] c_buff;

a_b2min u0_a_b2min(
                    .clk  (clk  ),
                    .rst_n(rst_n),
                    .a    (a    ),
                    .b    (b    ),
                    .c    (data0)
); 

always @ (posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    c_buff <= 8'b0;
  end
  else begin
    c_buff <= c;
  end
end

always @ (posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    d <= 8'b0;
  end
  else if (data0>c_buff) begin
    d <= c_buff;
  end
  else if (data0 <= c_buff) begin
    d <= data0;
  end
  else begin
    d <= 8'bz;
  end
end

endmodule

2、子模块

module a_b2min
(
//-- system signal
  input            clk  ,
  input            rst_n,

//-- input signal
  input      [7:0] a,
  input      [7:0] b,

//-- 
  output reg [7:0] c
);

always @ (posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    c <= 8'b0;
  end
  else if (a>b) begin
    c <= b;
  end
  else if (a <= b) begin
    c <= a;
  end
  else begin
    c <= 8'bz;
  end
end

endmodule

四、Testbench

`timescale 1ps/1ps
module tb_main_mod;
  reg        clk;
  reg        rst_n;
  reg  [7:0] a ;
  reg  [7:0] b ;
  reg  [7:0] c ;
  wire [7:0] d ;

/*-----------------------------------------------\
 --    --
\-----------------------------------------------*/
initial begin
  clk   = 1;
  rst_n   = 1;
  #1000 rst_n = 0;
  #4001 rst_n = 1;
    repeat(10000)begin
      d_case(a,b,c,{$random}%256,{$random}%256,{$random}%256);
      #5000 ;
  end
end

/*-----------------------------------------------\
 --    --
\-----------------------------------------------*/
task d_case;
  output  [7:0] a;
  output  [7:0] b;
  output  [7:0] c;
  input   [7:0] a0;
  input   [7:0] b0;
  input   [7:0] c0;

  begin
    a = a0 ;
    b = b0 ;
    c = c0 ;
  end
endtask

/*-----------------------------------------------\
 --  clock period is 5ns  --
\-----------------------------------------------*/
always begin
  #2500 clk = ~clk;
end

/*-----------------------------------------------\
 --  display  --
\-----------------------------------------------*/
//-- debug signal
reg [7:0] a1,a2;
reg [7:0] b1,b2;
reg [7:0] c1,c2;

always @ (posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    a1 <= 8'bz;
    a2 <= 8'bz;
    b1 <= 8'bz;
    b2 <= 8'bz;
    c1 <= 8'bz;
    c2 <= 8'bz;
  end
  else begin
    a1 <= a ;
    a2 <= a1;
    b1 <= b ;
    b2 <= b1;
    c1 <= c ;
    c2 <= c1;
  end
end

always @ (d)begin
  if((a2 > b2) && (a2 > c2))begin
    if((b2 > c2) && (d == c2))begin  
    end
    else if((b2 <= c2) && (d == b2))begin  
    end
    else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
    end
  end
  else if((b2 > a2) && (b2 > c2))begin
    if((a2 > c2) && (d == c2))begin  
    end
    else if((a2 <= c2) && (d == a2))begin  
    end
    else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
    end
  end
  else if((c2 > a2) && ( c2 > b2))begin
    if((a2 > b2) && (d == b2))begin  
    end
    else if((a2 <= b2) && (d == a2))begin  
    end
    else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
    end
  end
  else if((a2 == b2) || (a2 == c2) || (b2 == c2))begin
  end
  else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
  end
end

main_mod u_main_mod(
                     .clk(clk),
                     .rst_n(rst_n),
                     .a (a  ),
                     .b (b  ),
                     .c (c  ),
                     .d (d  )
                    );

initial #60000000 $finish;
initial begin
  $fsdbDumpfile("main_mod.fsdb");
  $fsdbDumpvars            ;
  $fsdbDumpMDA             ;
end
endmodule

五、结果分析

(1)TB结果

/*-----------------------------------------------\
 --  display  --
\-----------------------------------------------*/
//-- debug signal
reg [7:0] a1,a2;
reg [7:0] b1,b2;
reg [7:0] c1,c2;

always @ (posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    a1 <= 8'bz;
    a2 <= 8'bz;
    b1 <= 8'bz;
    b2 <= 8'bz;
    c1 <= 8'bz;
    c2 <= 8'bz;
  end
  else begin
    a1 <= a ;
    a2 <= a1;
    b1 <= b ;
    b2 <= b1;
    c1 <= c ;
    c2 <= c1;
  end
end

always @ (d)begin
  if((a2 > b2) && (a2 > c2))begin
    if((b2 > c2) && (d == c2))begin  
    end
    else if((b2 <= c2) && (d == b2))begin  
    end
    else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
    end
  end
  else if((b2 > a2) && (b2 > c2))begin
    if((a2 > c2) && (d == c2))begin  
    end
    else if((a2 <= c2) && (d == a2))begin  
    end
    else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
    end
  end
  else if((c2 > a2) && ( c2 > b2))begin
    if((a2 > b2) && (d == b2))begin  
    end
    else if((a2 <= b2) && (d == a2))begin  
    end
    else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
    end
  end
  else if((a2 == b2) || (a2 == c2) || (b2 == c2))begin
  end
  else begin
      $display($realtime,", error:a = %d ;b = %d;c = %d;d = %d",a2,b2,c2,d);
  end
end

在这里插入图片描述


可以看到,在a,b,c中如果出现x或z,则打印错误信息。


(2)波形图

在这里插入图片描述

由波形图可以知道,每次输出是输入的三个数据中的最小值。


(3)覆盖率

在这里插入图片描述

代码覆盖率100%


✍✍☛ 题库入口
  经过一段时间的沉淀,发现入行IC行业,自己的底子还是很差,写的文章质量参差不齐,也没能解答大家的疑问。决定还是要实打实从基础学起,由浅入深。因此决定通过补充/完善基础知识的同时,通过题库刷题不断提高自己的设计水平,题库推荐给大家(点击直达),<题库记录>栏目不定期更新,欢迎前来讨论。


作者:xlinxdu
版权:本文版权归作者所有
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到