流水线利用非阻塞赋值赋予的是上一时钟周期寄存器的值,来实现对寄存器的依次更新值。如:
always @ ( posedge CLK )
begin
//A[m]表示,一维数组A 中第m 个元素。
//A[m][n]表示,一维数组A 中第m 个元素,第n 位。
A[0] <= A_input; // 从外部读取新的A 值
A[1] <= A[0] | 4'b0001; // 读取A[0]值,并且设置第0 位,然后赋予A[1]
A[2] <= A[1] | 4'b0010; // 读取A[1]值,并且设置第1 位,然后赋予A[2]
A[3] <= A[2] | 4'b0100; // 读取A[2]值,并且设置第2 位,然后赋予A[3]
A[4] <= A[3] | 4'b1000; // 读取A[3]值,并且设置第3 位,然后赋予A[4]
end
虽然在一个时钟周期内,但完成A[4]的赋值仍需要5个时钟周期,这正是非阻塞赋值的特性,每次只能更新一次上一个时钟沿寄存器的值。虽然第一次需要5个时钟周期完成,但下一个数据的处理按照时钟的概念,依次进入某一拍子中进行处理,以后的数据处理将不需再等待所谓数据的“潜伏期”。如下图所示:当经过4个潜伏期之后,便会连续的输出结果。
顶层.v文件,例化方式采用位置例化方法,注意端口次序的先后对应:
1 module Stream_Line_Lut_Multiplier 2 ( 3 input CLK, 4 input RSTn, 5 6 input [7:0]A, 7 input [7:0]B, 8 9 output [15:0]Product 10 11 ); 12 13 /********************/ 14 15 wire [8:0]U1_I1_Out; 16 wire [8:0]U1_I2_Out; 17 18 task1_module U1( CLK, RSTn, A, B, U1_I1_Out, U1_I2_Out ); 19 20 wire [7:0]U2_I1_Out; 21 wire [7:0]U2_I2_Out; 22 23 task2_module U2( CLK, RSTn, U1_I1_Out, U1_I2_Out, U2_I1_Out, U2_I2_Out ); 24 25 wire [15:0]Q1_Sig; 26 wire [15:0]Q2_Sig; 27 28 lut_module U3a( CLK, U2_I1_Out, Q1_Sig ); 29 lut_module U3b( CLK, U2_I2_Out, Q2_Sig ); 30 31 /*************************/ 32 33 assign Product = Q1_Sig + ( ~Q2_Sig + 1'b1 ); 34 35 /*************************/ 36 37 endmodule 38 39 module task1_module 40 ( 41 42 input CLK, 43 input RSTn, 44 45 input [7:0]A, 46 input [7:0]B, 47 48 output [8:0]I1_Out, 49 output [8:0]I2_Out 50 51 ); 52 53 /***************************/ 54 55 reg [8:0]I1; 56 reg [8:0]I2; 57 58 always @ ( posedge CLK or negedge RSTn ) 59 if( !RSTn ) 60 begin 61 62 I1 <= 9'd0; 63 I2 <= 9'd0; 64 65 end 66 else 67 begin 68 69 I1 <= { A[7], A } + { B[7], B }; 70 I2 <= { A[7], A } + { ~B[7], ( ~B + 1'b1 ) }; 71 72 end 73 74 /***************************/ 75 76 assign I1_Out = I1; 77 assign I2_Out = I2; 78 79 /***************************/ 80 81 endmodule 82 83 84 85 module task2_module 86 ( 87 input CLK, 88 input RSTn, 89 90 input [8:0]I1_In, 91 input [8:0]I2_In, 92 93 output [7:0]I1_Out, 94 output [7:0]I2_Out 95 ); 96 97 /************************/ 98 99 reg [8:0]I1; 100 reg [8:0]I2; 101 102 always @ ( posedge CLK or negedge RSTn ) 103 if( !RSTn ) 104 begin 105 106 I1 <= 9'd0; 107 I2 <= 9'd0; 108 109 end 110 else 111 begin 112 113 I1 <= I1_In[8] ? ( ~I1_In + 1'b1 ) : I1_In; 114 I2 <= I2_In[8] ? ( ~I2_In + 1'b1 ) : I2_In; 115 116 end 117 118 /************************/ 119 120 assign I1_Out = I1[7:0]; 121 assign I2_Out = I2[7:0]; 122 123 /************************/ 124 125 endmodule