mul16
设计思想:乘法运算本身就可以看做是一个移位相加的过程
1 1 0 1 0 = 26
* 1 0 1 1 1 = 23
----------------------------- 23*26 = 598
1 1 0 1 0
1 1 0 1 0
1 1 0 1 0
0 0 0 0 0
1 1 0 1 0
----------------------------
10 0 1 0 1 0 1 1 0 = 598
核心是这个操作
result_reg <= { { ( 16 - clock_counter ){1'd0}}, // 31 - (clock_counter+14) -1
{ result_reg[clock_counter+14 : clock_counter-1] + a_reg },
{ result_reg[clock_counter-2 : 0]}
};
因为clock_counter <2 的时候,拼接操作 result_reg [clock_counter-2 : 0] 要成立
clock_counter>16 的时候,拼接操作{ ( 16 - clock_counter ){1'd0}} 要成立,(中间的那一部分相加是17bit,第31bit不应该补零)
所以要将他们单独拿出来讨论。
就以上思想进行设计,悲剧发生了
1 //date :2013/6/16 2 //designer :pengxiaoen 3 //function : unsigned 16 bit multiplication 4 5 6 module mul16 ( 7 clock,reset, 8 a_in,b_in, 9 status_mul16, 10 result_mul16 11 ); 12 13 input clock,reset; 14 input [15:0] a_in ,b_in; 15 output reg status_mul16; 16 output [31:0]result_mul16; 17 18 reg [4:0] clock_counter; 19 //-------------------------------------------- 20 always @ (posedge clock or negedge reset) 21 if (!reset) 22 clock_counter <= 5'd0; 23 else if(clock_counter == 5'd17) 24 clock_counter <= 5'd0; 25 else 26 clock_counter <= clock_counter + 1; 27 28 29 //----------------------------------------------- 30 always @ (posedge clock or negedge reset) 31 if(!reset) 32 status_mul16 <= 1'd0; 33 else if (clock_counter == 5'd17) 34 status_mul16 <= 1'd1; 35 else status_mul16 <= 1'd0; 36 37 38 reg [31:0] result_reg; 39 reg [15:0] a_reg,b_reg; 40 //------------------------------------------------ 41 always @ (posedge clock or negedge reset) 42 if (!reset) 43 begin 44 a_reg <= 16'd0; 45 b_reg <= 16'd0; 46 result_reg <= 32'd0; 47 end 48 else if (clock_counter == 5'd0) 49 begin 50 a_reg <= a_in; 51 b_reg <= b_in; 52 end 53 else if ((clock_counter >= 5'd1) && (clock_counter <= 5'd16)) 54 begin 55 if(b_reg [clock_counter -1]) 56 if(clock_counter == 5'd1) 57 result_reg <= result_reg + a_reg; 58 else if ((clock_counter >= 5'd2) & (clock_counter <= 5'd15)) 59 result_reg <= {{(16 - clock_counter ){1'd0}}, // 31 - (clock_counter+14) -1 60 {result_reg[clock_counter+14 : clock_counter-1] + a_reg}, 61 {result_reg[clock_counter-2 : 0]} 62 }; 63 else if(clock_counter == 5'd16) 64 result_reg <= {result_reg[30:15] + a_reg, result_reg[14:0]}; 65 else result_reg <= result_reg << 1; 66 end 67 68 assign result_mul16 = result_reg; 69 70 endmodule
编译产生的结果是:
因为错误提示是因为这个{ } 内部只能是常数,这个是因为语法约束导致的设计失败,那么我很想知道如果我采用门级建模是不是就避开了这个语法约束而实现呢?,但是门级建模,哎,头痛并且浩大的工作量啊。现在懒,不想搞门级建模
修正中..................
1 //date :2013/6/17 2 //designer :pengxiaoen 3 //function : unsigned 16 bit multiplication 4 5 6 module mul16 ( 7 clock,reset, 8 a_in,b_in, 9 data_in_en, //1 :data input enable 0:data input unenable 10 status_mul16, //1 :finish. 0:calculating 11 result_mul16 12 ); 13 14 input clock,reset; 15 input [15:0] a_in ,b_in; 16 output reg data_in_en; 17 output reg status_mul16; 18 output [31:0]result_mul16; 19 20 reg [4:0] clock_counter; 21 //-------------------------------------------- 22 always @ (posedge clock or negedge reset) 23 if (!reset) 24 clock_counter <= 5'd0; 25 else if(clock_counter >= 5'd17) 26 clock_counter <= 5'd0; 27 else 28 clock_counter <= clock_counter + 1; 29 30 //----------------------------------------------- 31 always @ (posedge clock or negedge reset) 32 if(!reset) 33 begin 34 status_mul16 <= 1'd0; 35 data_in_en <= 1'd0; 36 end 37 38 else case (clock_counter) 39 0 : data_in_en <= 1'd1; 40 17 : status_mul16 <= 1'd1; 41 default : begin 42 data_in_en<= 1'd0; 43 status_mul16 <= 1'd0; 44 end 45 endcase 46 47 48 49 reg [31:0] result_reg; 50 reg [15:0] a_reg,b_reg; 51 //------------------------------------------------ 52 always @ (posedge clock or negedge reset) 53 if (!reset) 54 begin 55 a_reg <= 16'd0; 56 b_reg <= 16'd0; 57 result_reg <= 32'd0; 58 end 59 else if (clock_counter == 5'd0) 60 begin 61 a_reg <= a_in; 62 b_reg <= b_in; 63 end 64 else if ((clock_counter >= 5'd1) && (clock_counter <= 5'd15)) 65 begin 66 if(b_reg[clock_counter -1]) 67 result_reg <= {1'b0, 68 result_reg [30:15] + a_reg, 69 result_reg [14:1] 70 }; 71 else result_reg <= result_reg >> 1; 72 end 73 else if ((b_reg[15]) && (clock_counter == 5'd16)) 74 result_reg [31: 16] <= {result_reg [31: 16] + a_reg}; 75 76 assign result_mul16 = result_reg; 77 78 endmodule
计算精华部分
64 else if ((clock_counter >= 5'd1) && (clock_counter <= 5'd15)) 65 begin 66 if(b_reg[clock_counter -1]) 67 result_reg <= {1'b0, 68 result_reg [30:15] + a_reg, 69 result_reg [14:1] 70 }; 71 else result_reg <= result_reg >> 1; 72 end 73 else if ((b_reg[15]) && (clock_counter == 5'd16)) 74 result_reg [31: 16] <= {result_reg [31: 16] + a_reg};
先运算reg中的[30:15] 部分,相加运算之后右移。最后第一个bit不就右移到最后去了嘛,为什么我当时就一定要在低位相加呢,不能倒过来呢,嘿嘿。自己愚钝了。
如果b_reg的当前bit是0 只需要右移
最后一个bit不需要移动,直接加到最高的 [31 :16 ] 就可以了。