5. RTL Coding

当前面部分设计的比较详细后,开始RTL代码编写,我使用的整个EDA工具都是在Linux上完成的,RTL代码使用GVIM编写。

Cycle级流水线bin2bcd代码如下:

`timescale 1ns/1ps

module bin2bcd ( 
    input       clk ,
    input       rst_n ,
    input   [10:0]  bin ,
    input           bin_vld ,

    output  [16:0]  bcd ,
    output          bcd_vld
 
);

reg             bin_abs_sym_bit ;
reg     [9:0]   bin_abs ;
reg             bin_abs_vld;

reg     [9:0]   bin_abs_d3 ;
reg     [3:0]   bin_abs_s3 ;
reg             bin_abs_s3_sym_bit ;
reg             bin_abs_d3_vld ;

reg     [9:0]   bin_abs_d2 ;
reg     [3:0]   bin_abs_s2 ;
reg     [3:0]   bin_abs_s2_s3_tmp ;
reg             bin_abs_s2_sym_bit ;
reg             bin_abs_d2_vld ;

reg     [9:0]   bin_abs_d1 ;
reg     [3:0]   bin_abs_s1 ;
reg     [3:0]   bin_abs_s1_s2_tmp;
reg     [3:0]   bin_abs_s1_s3_tmp ;
reg             bin_abs_s1_sym_bit ;
reg             bin_abs_d1_vld ;

reg     [3:0]   bin_abs_s0 ;
reg     [3:0]   bin_abs_s0_s1_tmp;
reg     [3:0]   bin_abs_s0_s2_tmp;
reg     [3:0]   bin_abs_s0_s3_tmp;
reg             bin_abs_s0_sym_bit ;
reg             bin_abs_d0_vld ;


always @ (posedge clk) begin
    if(!rst_n) begin
        bin_abs <=  10'd0 ;
        bin_abs_vld <=  1'b0 ;
        bin_abs_sym_bit <= 1'b0 ;
    end else if(bin_vld) begin
        if(bin[10]==1'b0begin 
            bin_abs <=  bin[9:0] ;
            bin_abs_sym_bit <= 1'b0 ;
            bin_abs_vld <=  1'b1 ;
        end else begin
            bin_abs <=  11'd1024-bin[9:0] ;
            bin_abs_sym_bit <= 1'b1 ;
            bin_abs_vld <=  1'b1 ;
        end
    end else begin 
        bin_abs <=  10'd0 ;
        bin_abs_sym_bit <= 1'b0 ;
        bin_abs_vld <=  1'b0 ;
    end
end

always @(posedge clk) begin
    if(!rst_n) begin
        bin_abs_s3  <=  4'h0 ;
        bin_abs_d3  <=  10'd0 ;
        bin_abs_s3_sym_bit <= 1'b0 ;
        bin_abs_d3_vld <=   1'b0 ;
    end else if(bin_abs_vld) begin
        if(bin_abs >= 10'd1000begin 
            bin_abs_s3 <=   4'h1 ;
            bin_abs_d3 <=   bin_abs - 10'd1000 ;
        end
        else begin 
            bin_abs_s3  <=  4'h0 ;
            bin_abs_d3  <=  bin_abs ; 
        end begin
            bin_abs_s3_sym_bit <= bin_abs_sym_bit ;
            bin_abs_d3_vld <= 1'b1 ;
        end
    end else begin 
        bin_abs_s3 <= 4'h0 ;
        bin_abs_s3_sym_bit <= 1'b0 ;
        bin_abs_d3 <= 10'd0;
        bin_abs_d3_vld <= 1'b0 ;
    end
end

always @ (posedge clk) begin 
    if(!rst_n) begin 
        bin_abs_s2  <=  4'h0 ;
        bin_abs_s2_s3_tmp <= 4'h0 ;
        bin_abs_s2_sym_bit <= 1'b0 ;
        bin_abs_d2  <=  10'd0 ;
        bin_abs_d2_vld <=   1'b0 ;
    end else if(bin_abs_d3_vld) begin 
        if(bin_abs_d3 >= 10'd900begin 
            bin_abs_s2  <=  4'h9 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd900 ;
        end else if(bin_abs_d3 >= 10'd800begin 
            bin_abs_s2  <=  4'h8 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd800 ;
        end else if(bin_abs_d3 >= 10'd700begin 
            bin_abs_s2  <=  4'h7 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd700 ;
        end else if(bin_abs_d3 >= 10'd600begin 
            bin_abs_s2  <=  4'h6 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd600 ;
        end else if(bin_abs_d3 >= 10'd500begin 
            bin_abs_s2  <=  4'h5 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd500 ;
        end else if(bin_abs_d3 >= 10'd400begin 
            bin_abs_s2  <=  4'h4 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd400 ;
        end else if(bin_abs_d3 >= 10'd300begin 
            bin_abs_s2  <=  4'h3 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd300 ;
        end else if(bin_abs_d3 >= 10'd200begin 
            bin_abs_s2  <=  4'h2 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd200 ;
        end else if(bin_abs_d3 >= 10'd100begin 
            bin_abs_s2  <=  4'h1 ;
            bin_abs_d2  <=  bin_abs_d3 - 10'd100 ;
        end else begin 
            bin_abs_s2  <=  4'h0 ;
            bin_abs_d2  <=  bin_abs_d3 ;
        end begin
            bin_abs_d2_vld  <=  1'b1 ;
            bin_abs_s2_s3_tmp <= bin_abs_s3 ; 
            bin_abs_s2_sym_bit <= bin_abs_s3_sym_bit ;
        end
    end else begin 
        bin_abs_s2  <=  4'h0 ;
        bin_abs_s2_s3_tmp <= 4'h0 ;
        bin_abs_s2_sym_bit <= 1'b0 ;
        bin_abs_d2  <=  10'd0 ;
        bin_abs_d2_vld <=   1'b0 ;
    end
end
 
 always @ (posedge clk) begin 
    if(!rst_n) begin 
        bin_abs_s1  <=  4'h0 ;
        bin_abs_s1_s2_tmp <= 4'h0;
        bin_abs_s1_s3_tmp <= 4'h0;
        bin_abs_s1_sym_bit <= 1'b0 ;
        bin_abs_d1  <=  10'd0 ;
        bin_abs_d1_vld <=   1'b0 ;
    end else if(bin_abs_d2_vld) begin 
        if(bin_abs_d2 >= 10'd90begin 
            bin_abs_s1  <=  4'h9 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd90 ;
        end else if(bin_abs_d2 >= 10'd80begin 
            bin_abs_s1  <=  4'h8 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd80 ;
        end else if(bin_abs_d2 >= 10'd70begin 
            bin_abs_s1  <=  4'h7 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd70 ;
        end else if(bin_abs_d2 >= 10'd60begin 
            bin_abs_s1  <=  4'h6 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd60 ;
        end else if(bin_abs_d2 >= 10'd50begin 
            bin_abs_s1  <=  4'h5 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd50 ;
        end else if(bin_abs_d2 >= 10'd40begin 
            bin_abs_s1  <=  4'h4 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd40 ;
        end else if(bin_abs_d2 >= 10'd30begin 
            bin_abs_s1  <=  4'h3 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd30 ;
        end else if(bin_abs_d2 >= 10'd20begin 
            bin_abs_s1  <=  4'h2 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd20 ;
        end else if(bin_abs_d2 >= 10'd10begin 
            bin_abs_s1  <=  4'h1 ;
            bin_abs_d1  <=  bin_abs_d2 - 10'd10 ;
        end else begin 
            bin_abs_s1  <=  4'h0 ;
            bin_abs_d1  <=  bin_abs_d2 ;
        end begin
            bin_abs_d1_vld  <=  1'b1 ;
            bin_abs_s1_s2_tmp <= bin_abs_s2 ;
            bin_abs_s1_s3_tmp <= bin_abs_s2_s3_tmp;
            bin_abs_s1_sym_bit <= bin_abs_s2_sym_bit ;
         end 
    end else begin 
        bin_abs_s1  <=  4'h0 ;
        bin_abs_d1  <=  10'd0 ;
        bin_abs_s1_s2_tmp <= 4'h0;
        bin_abs_s1_s3_tmp <= 4'h0;
        bin_abs_s1_sym_bit <= 1'b0 ;
        bin_abs_d1_vld <=   1'b0 ;
    end
end
 
  
 always @ (posedge clk) begin 
    if(!rst_n) begin 
        bin_abs_s0  <=  4'h0 ;
        bin_abs_s0_s1_tmp <= 4'h0;
        bin_abs_s0_s2_tmp <= 4'h0;
        bin_abs_s0_s3_tmp <= 4'h0;
        bin_abs_s0_sym_bit <= 1'b0 ;
        bin_abs_d0_vld <=   1'b0 ;
    end else if(bin_abs_d1_vld) begin 
        if(bin_abs_d1 == 10'd9begin 
            bin_abs_s0  <=  4'h9 ;
        end else if(bin_abs_d1 == 10'd8begin 
            bin_abs_s0  <=  4'h8 ;
        end else if(bin_abs_d1 == 10'd7begin 
            bin_abs_s0  <=  4'h7 ;
        end else if(bin_abs_d1 == 10'd6begin 
            bin_abs_s0  <=  4'h6 ;
        end else if(bin_abs_d1 == 10'd5begin
            bin_abs_s0  <=  4'h5 ;
        end else if(bin_abs_d1 == 10'd4begin 
            bin_abs_s0  <=  4'h4 ;
        end else if(bin_abs_d1 == 10'd3begin 
            bin_abs_s0  <=  4'h3 ;
        end else if(bin_abs_d1 == 10'd2begin 
            bin_abs_s0  <=  4'h2 ;
        end else if(bin_abs_d1 == 10'd1begin 
            bin_abs_s0  <=  4'h1 ;
        end else begin 
            bin_abs_s0  <=  4'h0 ;
        end begin
            bin_abs_s0_s1_tmp <= bin_abs_s1 ;
            bin_abs_s0_s2_tmp <= bin_abs_s1_s2_tmp ;
            bin_abs_s0_s3_tmp <= bin_abs_s1_s3_tmp ;
            bin_abs_s0_sym_bit <= bin_abs_s1_sym_bit ;
            bin_abs_d0_vld  <=  1'b1 ; 
        end
    end else begin 
        bin_abs_s0  <=  4'h0 ;
        bin_abs_s0_s1_tmp <= 4'h0;
        bin_abs_s0_s2_tmp <= 4'h0;
        bin_abs_s0_s3_tmp <= 4'h0;
        bin_abs_s0_sym_bit <= 1'b0 ; 
        bin_abs_d0_vld <=   1'b0 ;
    end
end

assign bcd = {  bin_abs_s0_sym_bit  , 
                bin_abs_s0_s3_tmp   ,
                bin_abs_s0_s2_tmp   ,
                bin_abs_s0_s1_tmp   ,
                bin_abs_s0              } ;

assign bcd_vld = bin_abs_d0_vld ;

endmodule

6. RTL功能仿真验证

RTL编写完之后需要搭建仿真验证环境,好的仿真环境是,第一,能够产生出足够多的测试向量,把功能覆盖全面;第二,能够自动仿真并与Gold_Trace自动比对,若出现仿真结果与Gold_Trace结果不一致时,自动停止并告知Fail,若测试点全部自动比对完成,无误,自动停止并告知测试Pass。

本例bin2bcd的测试点可以分解为如下:

  1. bin值需要覆盖全面,从[-1023, 1023]。
  2. bin_vld具有随机性,可随机为1’b1或1’b0。

通过以上测试点分解,本例bin2bcd测试主要有:

  1. bin值顺序的从-1023到1023全覆盖,bin_vld值在[-1023, 1023]全有效;
  2. bin值顺序的从-1023到1023全覆盖,bin_vld值在[-1023, 1023]随机为1’b1或1’b0;
  3. bin值在[-1023, 1023]区间内随机,bin_vld值在[-1023, 1023]随机,测试5000次。

在Linux下建立Modelsim自动仿真比对环境,只需在仿真文件夹终端输入vsim -do run_sim.do即可开始编译,仿真,并自动比对,显示Fail或Pass。如下图。