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'b0) begin
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'd1000) begin
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'd900) begin
bin_abs_s2 <= 4'h9 ;
bin_abs_d2 <= bin_abs_d3 - 10'd900 ;
end else if(bin_abs_d3 >= 10'd800) begin
bin_abs_s2 <= 4'h8 ;
bin_abs_d2 <= bin_abs_d3 - 10'd800 ;
end else if(bin_abs_d3 >= 10'd700) begin
bin_abs_s2 <= 4'h7 ;
bin_abs_d2 <= bin_abs_d3 - 10'd700 ;
end else if(bin_abs_d3 >= 10'd600) begin
bin_abs_s2 <= 4'h6 ;
bin_abs_d2 <= bin_abs_d3 - 10'd600 ;
end else if(bin_abs_d3 >= 10'd500) begin
bin_abs_s2 <= 4'h5 ;
bin_abs_d2 <= bin_abs_d3 - 10'd500 ;
end else if(bin_abs_d3 >= 10'd400) begin
bin_abs_s2 <= 4'h4 ;
bin_abs_d2 <= bin_abs_d3 - 10'd400 ;
end else if(bin_abs_d3 >= 10'd300) begin
bin_abs_s2 <= 4'h3 ;
bin_abs_d2 <= bin_abs_d3 - 10'd300 ;
end else if(bin_abs_d3 >= 10'd200) begin
bin_abs_s2 <= 4'h2 ;
bin_abs_d2 <= bin_abs_d3 - 10'd200 ;
end else if(bin_abs_d3 >= 10'd100) begin
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'd90) begin
bin_abs_s1 <= 4'h9 ;
bin_abs_d1 <= bin_abs_d2 - 10'd90 ;
end else if(bin_abs_d2 >= 10'd80) begin
bin_abs_s1 <= 4'h8 ;
bin_abs_d1 <= bin_abs_d2 - 10'd80 ;
end else if(bin_abs_d2 >= 10'd70) begin
bin_abs_s1 <= 4'h7 ;
bin_abs_d1 <= bin_abs_d2 - 10'd70 ;
end else if(bin_abs_d2 >= 10'd60) begin
bin_abs_s1 <= 4'h6 ;
bin_abs_d1 <= bin_abs_d2 - 10'd60 ;
end else if(bin_abs_d2 >= 10'd50) begin
bin_abs_s1 <= 4'h5 ;
bin_abs_d1 <= bin_abs_d2 - 10'd50 ;
end else if(bin_abs_d2 >= 10'd40) begin
bin_abs_s1 <= 4'h4 ;
bin_abs_d1 <= bin_abs_d2 - 10'd40 ;
end else if(bin_abs_d2 >= 10'd30) begin
bin_abs_s1 <= 4'h3 ;
bin_abs_d1 <= bin_abs_d2 - 10'd30 ;
end else if(bin_abs_d2 >= 10'd20) begin
bin_abs_s1 <= 4'h2 ;
bin_abs_d1 <= bin_abs_d2 - 10'd20 ;
end else if(bin_abs_d2 >= 10'd10) begin
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'd9) begin
bin_abs_s0 <= 4'h9 ;
end else if(bin_abs_d1 == 10'd8) begin
bin_abs_s0 <= 4'h8 ;
end else if(bin_abs_d1 == 10'd7) begin
bin_abs_s0 <= 4'h7 ;
end else if(bin_abs_d1 == 10'd6) begin
bin_abs_s0 <= 4'h6 ;
end else if(bin_abs_d1 == 10'd5) begin
bin_abs_s0 <= 4'h5 ;
end else if(bin_abs_d1 == 10'd4) begin
bin_abs_s0 <= 4'h4 ;
end else if(bin_abs_d1 == 10'd3) begin
bin_abs_s0 <= 4'h3 ;
end else if(bin_abs_d1 == 10'd2) begin
bin_abs_s0 <= 4'h2 ;
end else if(bin_abs_d1 == 10'd1) begin
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的测试点可以分解为如下:
-
bin值需要覆盖全面,从[-1023, 1023]。 -
bin_vld具有随机性,可随机为1’b1或1’b0。
通过以上测试点分解,本例bin2bcd测试主要有:
-
bin值顺序的从-1023到1023全覆盖,bin_vld值在[-1023, 1023]全有效; -
bin值顺序的从-1023到1023全覆盖,bin_vld值在[-1023, 1023]随机为1’b1或1’b0; -
bin值在[-1023, 1023]区间内随机,bin_vld值在[-1023, 1023]随机,测试5000次。
在Linux下建立Modelsim自动仿真比对环境,只需在仿真文件夹终端输入vsim -do run_sim.do
即可开始编译,仿真,并自动比对,显示Fail或Pass。如下图。