组合逻辑与$display
这次发现的问题其实还是很有代表性的 是关于系统函数与组合逻辑的时刻取指问题
问题发现的缘由是 本来想写一个纯组合逻辑运算的电路 用display的方式把每次的结果显示出来 于是便有了下文
首先先看一下代码
1 //////////////////////////////////////////////////////////////////////////////// 2 // MODULE NAME : gray_code // 3 // DATE : Thu Aug 23 11:05:54 CST 2012 // 4 // DESCRIPTION : gray_code template test for dual n-bit Gray // 5 // code counter encoder/decoder // 6 // VERSION : 1.0 // 7 //////////////////////////////////////////////////////////////////////////////// 8 module gray_code #(parameter WIDTH=4)( 9 input wire [WIDTH-1:0] bin_in 10 , output wire [WIDTH-1:0] gray_enc 11 , output wire [WIDTH-2:0] gray_enc_minus 12 , output reg [WIDTH-1:0] bin_dec 13 ); 14 //////////////////////////////////////////////////////////////////////////////// 15 //////////////////////////////////////////////////////////////////////////////// 16 assign gray_enc = {bin_in[WIDTH-1], bin_in[WIDTH-1:1] ^ bin_in[WIDTH-2:0]} ; 17 assign gray_enc_minus = {gray_enc[WIDTH-1] ^ gray_enc[WIDTH-2], gray_enc[WIDTH-3:0]}; 18 always @(*) begin: proc_gray_dec 19 integer m; 20 bin_dec = 'b0; 21 bin_dec[WIDTH-1] = gray_enc[WIDTH-1]; 22 for(m=WIDTH-1;m>0;m=m-1) 23 bin_dec[m-1] = bin_dec[m] ^ gray_enc[m-1]; 24 end 25 //////////////////////////////////////////////////////////////////////////////// 26 27 endmodule // CREATED BY poiu_elab@1207 28 29 ////////////////////////////////////////////////////////////////////////////////
这里的代码是个纯组合逻辑运算gray码与解gray码的电路 没啥新鲜的 再看看testbench
1 //////////////////////////////////////////////////////////////////////////////// 2 // DATE : Thu Aug 23 11:37:04 CST 2012 3 //////////////////////////////////////////////////////////////////////////////// 4 `timescale 1ns/100ps 5 `define CLK_OSC 20 6 `define CLK_CYCLE (1000.0/2.0/`CLK_OSC) 7 `define WIDTH 4 8 `define FOR_SESSION_RIGHT 9 //`define FOR_SESSION_WRONG 10 //`define REPEAT_SESSION 11 12 module tb(); 13 //////////////////////////////////////////////////////////////////////////////// 14 reg [`WIDTH-1:0] bin_in ; 15 wire [`WIDTH-1:0] gray_enc ; 16 wire [`WIDTH-2:0] gray_enc_minus ; 17 wire [`WIDTH-1:0] bin_dec ; 18 19 reg [`WIDTH:0] k ; 20 //////////////////////////////////////////////////////////////////////////////// 21 // stimulation generation 22 initial begin: proc_sti_gen 23 bin_in = 'bx ; 24 k=0; 25 //------------------------------------------------------------------------------ 26 `ifdef FOR_SESSION_RIGHT 27 $display("\tk\t\tbin_in\t\tgray_en\t\tgray_enc_minus\tbin_dec\n"); 28 for(k=0;k<(1<<`WIDTH);k=k+1) begin 29 bin_in = k ; 30 #(`CLK_CYCLE); 31 //$monitor("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); 32 $display("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); 33 end 34 //------------------------------------------------------------------------------ 35 `elsif FOR_SESSION_WRONG 36 $display("\tk\t\tbin_in\t\tgray_en\t\tgray_enc_minus\tbin_dec\n"); 37 for(k=0;k<(1<<`WIDTH);k=k+1) begin 38 #(`CLK_CYCLE) bin_in = k ; 39 //$monitor("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); 40 //$strobe("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); 41 $display("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); 42 end 43 //------------------------------------------------------------------------------ 44 `elsif REPEAT_SESSION 45 $display("\tk\t\tbin_in\t\tgray_en\t\tgray_enc_minus\tbin_dec\n"); 46 repeat(1<<`WIDTH) begin 47 bin_in = k; 48 #(`CLK_CYCLE) 49 $display("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); 50 k=k+1; 51 end 52 `endif 53 //------------------------------------------------------------------------------ 54 #(50*`CLK_CYCLE); 55 $stop; 56 end 57 //////////////////////////////////////////////////////////////////////////////// 58 gray_code #(`WIDTH)u_gray_code( 59 . bin_in ( bin_in ) 60 , . gray_enc ( gray_enc ) 61 , . gray_enc_minus ( gray_enc_minus ) 62 , . bin_dec ( bin_dec ) 63 ); 64 //////////////////////////////////////////////////////////////////////////////// 65 66 endmodule // CREATED BY poiu_elab@1207 67 68 ////////////////////////////////////////////////////////////////////////////////
这里的3种显示方式 第1种是可以正常显示的for session,第2种是不能正常显示的for session,第3种是能正常显示的repeat session,正常显示的值是什么呢 是这样的
k bin_in gray_en gray_enc_minus bin_dec 0 0000 0000 000 0000 1 0001 0001 001 0001 2 0010 0011 011 0010 3 0011 0010 010 0011 4 0100 0110 110 0100 5 0101 0111 111 0101 6 0110 0101 101 0110 7 0111 0100 100 0111 8 1000 1100 000 1000 9 1001 1101 001 1001 10 1010 1111 011 1010 11 1011 1110 010 1011 12 1100 1010 110 1100 13 1101 1011 111 1101 14 1110 1001 101 1110 15 1111 1000 100 1111
不正常的显示是什么样的呢
k bin_in gray_en gray_enc_minus bin_dec 0 0000 xxxx xxx xxxx 1 0001 0000 000 0000 2 0010 0001 001 0001 3 0011 0011 011 0010 4 0100 0010 010 0011 5 0101 0110 110 0100 6 0110 0111 111 0101 7 0111 0101 101 0110 8 1000 0100 100 0111 9 1001 1100 000 1000 10 1010 1101 001 1001 11 1011 1111 011 1010 12 1100 1110 010 1011 13 1101 1010 110 1100 14 1110 1011 111 1101 15 1111 1001 101 1110
而正常的与不正常的差在了哪里呢 就是display的位置 其实错误的case也是我没太注意的地方写到的 按照的正常的写法
for(k=0;k<(1<<`WIDTH);k=k+1) begin bin_in = k ; #(`CLK_CYCLE); //$monitor("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); $display("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); end
首先先对bin_in赋值k,之后延迟一段时间 再用$display读出所有变量的值,而错误的呢
for(k=0;k<(1<<`WIDTH);k=k+1) begin #(`CLK_CYCLE) bin_in = k ; //$monitor("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); //$strobe("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); $display("\t%d\t\t%b\t\t%b\t\t%b\t\t%b\n", k, bin_in, gray_enc, gray_enc_minus, bin_dec); end
是将bin_in赋值k,之后立刻就用系统函数$display读出所有变量的值,这里我理解可以把$display看成是一个阻塞赋值语句,进行到它的时候,虽然说硬件是并行的,但不是真正并行的,执行到display的时候就先把display需要的值给到display输出的变量里面,再接着把bin_in的值给到gray_code这个模块里面供各个wire进行组合逻辑运算。所以display就能在各个wire的组合逻辑运算之前拿到各个变量的值 从而出现如上所示的情况 所以这点还是要注意一下的
这次算是误打误撞碰到的这个现象在变化的沿处进行的操作就尤其要注意这种东西 至此 完结