通常编写testbench观察仿真波形的方法,对于简单直观的电路功能验证来说很方便,但当电路输出比较复杂时,就比较无趣.这里以七段数码管的译码电路为例,编写了一个发函数功能的模块来验证其功能.所谓反函数就是把设计模块的输入输出端颠倒一下,衔接在设计模块后面,然后验证输入和输出是否一样,就这么简单.
代码1:七段数码管(共阳)译码电路.
//----------------------------------------------------------------------
// define segment codes
// seven bit code - one bit per segment, segment is illuminated when
// bit is high. Bits 6543210 correspond to:
//
// 6666
// 1 5
// 1 5
// 0000
// 2 4
// 2 4
// 3333
//
//----------------------------------------------------------------------
`define SS_0 7'b1111110
`define SS_1 7'b0110000
`define SS_2 7'b1101101
`define SS_3 7'b1111001
`define SS_4 7'b0110011
`define SS_5 7'b1011011
`define SS_6 7'b1011111
`define SS_7 7'b1110000
`define SS_8 7'b1111111
`define SS_9 7'b1111011
//----------------------------------------------------------------------
// sseg - converts a 4-bit binary number to seven segment code
//
// bin - 4-bit binary input
// segs - 7-bit output, defined above
//----------------------------------------------------------------------
module sseg(bin, segs) ;
input [3:0] bin ; // four-bit binary input
output [6:0] segs ; // seven segments
reg [6:0] segs ;
always@(bin) begin
case(bin)
0: segs = `SS_0 ;
1: segs = `SS_1 ;
2: segs = `SS_2 ;
3: segs = `SS_3 ;
4: segs = `SS_4 ;
5: segs = `SS_5 ;
6: segs = `SS_6 ;
7: segs = `SS_7 ;
8: segs = `SS_8 ;
9: segs = `SS_9 ;
default: segs = 7'b0000000 ;
endcase
end
endmodule
这电路很常见,没什么好说的.无非就是用了define语句,这样利人利己,便于维护和阅读.
代码2:七段数码管译码电路的反函数模块.
//----------------------------------------------------------------------
// invsseg - converts seven segment code to binary - signals if valid
//
// segs - seven segment code in
// bin - binary code out
// valid - true if input is a valid seven segment code
//
// segs = legal code (0-9) ==> valid = 1, bin = binary
// segs = zero ==> valid = 0, bin = 0
// segs = any other code ==> valid = 0, bin = 1
//----------------------------------------------------------------------
//----------------------------------------------------------------------
`define SS_0 7'b1111110
`define SS_1 7'b0110000
`define SS_2 7'b1101101
`define SS_3 7'b1111001
`define SS_4 7'b0110011
`define SS_5 7'b1011011
`define SS_6 7'b1011111
`define SS_7 7'b1110000
`define SS_8 7'b1111111
`define SS_9 7'b1111011
module invsseg(segs, bin, valid) ;
input [6:0] segs ; // seven segment code in
output [3:0] bin ; // four-bit binary output
output valid ; // true if input code is valid
reg [3:0] bin ;
reg valid ;
always@(segs) begin
case(segs)
`SS_0: {valid,bin} = 5'h10 ;
`SS_1: {valid,bin} = 5'h11 ;
`SS_2: {valid,bin} = 5'h12 ;
`SS_3: {valid,bin} = 5'h13 ;
`SS_4: {valid,bin} = 5'h14 ;
`SS_5: {valid,bin} = 5'h15 ;
`SS_6: {valid,bin} = 5'h16 ;
`SS_7: {valid,bin} = 5'h17 ;
`SS_8: {valid,bin} = 5'h18 ;
`SS_9: {valid,bin} = 5'h19 ;
0: {valid,bin} = 5'h00 ;
default: {valid,bin} = 5'h01 ;
endcase
end
endmodule
这个反函数模块,就是把代码1颠倒过来.难点就在于case里0和default那两行,0那一行还比较好理解,因为设计模块的case最后有default输出是0.但这里又加一条default,从单独的电路设计上来说,肯定不多余,因为输入的信号可能在限定之外.但是输入的数据是多少,其实不重要,但对于设计电路来说,这两种肯定都是不需要的情况,所以valid都是0,这点很重要,后面的测试文件里就是利用了valid是0,直接排出非法情况.
代码3:testbench
//----------------------------------------------------------------------
// test seven segment decoder - using inverse decoder for a check
// note that both coders use the same set of defines so an
// error in the defines will not be caught.
//----------------------------------------------------------------------
module test_sseg ;
reg [3:0] bin_in ; // binary code in
wire [6:0] segs ; // segment code
wire [3:0] bin_out ; // binary code out of inverse coder
wire valid ; // valid out of inverse coder
reg error ;
// instantiate decoder and checker
sseg ss(bin_in, segs) ;
invsseg iss(segs, bin_out, valid) ;
// walk through all 16 inputs
initial begin
bin_in = 0 ; error = 0 ;
repeat (16) begin
#100
// uncomment the following line to display each case
// $display("%h %b %h %b",bin_in,segs, bin_out, valid) ;
if(bin_in < 10) begin
if((bin_in != bin_out)||(valid != 1)) begin
$display("ERROR: %h %b %h %b",bin_in,segs, bin_out, valid) ;
error = 1 ;
end
end
else begin
if((bin_out != 0) || (valid != 0)) begin
$display("ERROR: %h %b %h %b",bin_in,segs, bin_out, valid) ;
error = 1 ;
end
end
bin_in = bin_in+1 ;
end
if(error == 0) $display("TEST PASSED") ;
end
endmodule
这里主要分了3段来测试,第一种是0-9,bin_in==bin_out,并且valid==1,不满足就报错;第二种是bin_out==0,并且valid==0,不满足,就报错。
1.《Digital Design,A systems Approach》William Dally & R.Curtis Harting,Cambridge University Press,Page 122.