今天重新补习了一下二进制原码,反码和补码之间的关系以及正数变负数,负数变正数之间的关系。瞬间感觉好晕,赶紧仔细研究:
原码就是符号位加上真值的绝对值。正数原码是其本身,负数符号位为1.
正数的反码和补码都是其本身,负数反码为符号位不变,其余各位依次取反;补码为符号位不变,其余各位依次取反后加1。
这都好理解,那一个正数怎么变为负数呢?
注意计算机内存储负数是其补码形式! 正数取反后加1就得到负数(其实是负数的补码),例如:7二进制为0111;取反后为1000;然后+1为1001=(-7)补码。
同理负数取反+1后得到正数的补码=正数本身。
好了理清了上述关系 下面实现一个booth算法乘法器:
booth算法其实就是一种位操作,直接上例子
bit[1]
bit[2]
位操作
0
0
无操作
0
1
+被乘数
1
0
-被乘数
1
1
无操作
例如4*2 被乘数为4(0100),乘数为2(0010),都为4bit,因此result应有9bit空间。
第一步:被乘数正数:0100 负数为:1100,result={4’d0,0010,0}
第二步:判断result[1:0] ,为00 则无操作,result向右移一位,补高位与原来高位一致为result={4’d0,0001,0}
第三步:判断result[1:0],为10则减被乘数,result[9:6]+4’b1100={1100,0001,0},result向右移一位,高位补1,result={1110,0000,1}
第四步:判断result[1:0],为01则加被乘数,result[9:6]+4’b0100={0010,0000,1},result向右移一位,高位补0,result={0001,0000,0}
第五步:判断result[1:0],为00则无操作,result向右移一位,高位补0,result={0000,0001,0}
第六步:最后结果取result[9:1]={0000,1000}=8;
中间判断次数为寄存器宽度,即4bit执行4次,然后去高8为最后结果。
下面为位宽8bit的booth乘法器verilog代码:
//-----------------------------------------------------------------------------//Title :
//Project : //-----------------------------------------------------------------------------//File : multiplier.v//Author : caoshan//Created : //Last modified : //-----------------------------------------------------------------------------//Description :-----------------------------------------------------------------------------//Copyright (c) by This model is the confidential and//proprietary property of and the possession or use of this//file requires a written license from .//------------------------------------------------------------------------------//Modification history :-----------------------------------------------------------------------------module multiplier(/*autoarg*/
//Outputs
done_flag, mul_result,//Inputs
clk, rst_n, start_en, mul_cand_data, mul_data
);//parameter WIDTH = 8;//system interface
inputclk;inputrst_n;inputstart_en;input [7:0] mul_cand_data;input [7:0] mul_data;outputdone_flag;output [15:0] mul_result;/*autoinput*/
/*autooutput*/
/*autoreg*/
//Beginning of automatic regs (for this module's undeclared outputs)
regdone_flag;//reg [2*WIDTH-1:0] mul_result;//End of automatics
/*autowire*/
//===========================================================//state machine//=======================================================
parameter IDLE = 3'd0;
parameter LOCK_DATA = 3'd1;
parameter IMPROVE_MC = 3'd2;
parameter IMPROVE_M = 3'd3;
parameter JUDGE = 3'd4;
parameter MUL_MOV = 3'd5;
parameter MUL_END = 3'd6;
reg [2:0] curr_state;reg [2:0] next_state;reg [7:0] mul_cand_data_ff1;reg [7:0] mul_cand_data_ff2;reg [7:0] mul_data_ff;reg [16:0] mul_result_ff;reg [7:0] cnt;always @ (posedge clk or negedge rst_n)begin
if(rst_n == 0)
curr_state<=IDLE;elsecurr_state<=next_state;end
always @ (*)beginnext_state=IDLE;case(curr_state)
IDLE:begin
if(start_en)
next_state=LOCK_DATA;elsenext_state=IDLE;endLOCK_DATA:beginnext_state=IMPROVE_MC;endIMPROVE_MC:beginnext_state=IMPROVE_M;endIMPROVE_M:beginnext_state=JUDGE;endJUDGE:beginnext_state=MUL_MOV;endMUL_MOV:begin
if(cnt >= 7)
next_state=MUL_END;elsenext_state=JUDGE;endMUL_END:beginnext_state=IDLE;end
default: next_state =IDLE;endcase //case (curr_state)
end //always @ (*)//-------------------------------------//state machine change
always@(posedge clk or negedge rst_n)begin
if(rst_n==0)beginmul_cand_data_ff1<= 0;
mul_cand_data_ff2<= 0;
mul_data_ff<= 0;end
else if(curr_state == IMPROVE_MC)beginmul_cand_data_ff1<=mul_cand_data;
mul_cand_data_ff2<= ~mul_cand_data + 1'b1;
mul_data_ff <=mul_data;end
end
always @ (posedge clk or negedge rst_n)begin
if(rst_n == 0)
mul_result_ff<= 0;else if(curr_state ==IMPROVE_M)
mul_result_ff<= {8'd0,mul_data_ff,1'b0};else if(curr_state == JUDGE)begin
if(mul_result_ff[1:0]==2'b01)
mul_result_ff <= {(mul_result_ff[16:9] + mul_cand_data_ff1[7:0]),mul_result_ff[8:0]};else if(mul_result_ff[1:0]== 2'b10)
mul_result_ff <= {(mul_result_ff[16:9] + mul_cand_data_ff2[7:0]),mul_result_ff[8:0]};end
else if(curr_state ==MUL_MOV)
mul_result_ff<= {mul_result_ff[16],mul_result_ff[16:1]};end //always @ (posedge clk or negedge rst_n)
always @ (posedge clk or negedge rst_n)begin
if(rst_n == 0)
cnt<= 0;else if((curr_state == MUL_MOV)&&(cnt < 7))
cnt<= cnt + 1'b1;
else if((cnt >=7 )&&(curr_state ==MUL_END))
cnt<= 0;end
always@(posedge clk or negedge rst_n)begin
if(rst_n == 0)
done_flag<= 0;else if(curr_state ==MUL_END)
done_flag<= 1;elsedone_flag<= 0;end
reg[16:0] mul_result_ff2;always @ (posedge clk or negedge rst_n)begin
if(rst_n == 0)
mul_result_ff2<= 0;else if(curr_state ==MUL_END)
mul_result_ff2<=mul_result_ff;end
assign mul_result = mul_result_ff2[16:1];endmodule //
testbench:
//-----------------------------------------------------------------------------//Title :
//Project : //-----------------------------------------------------------------------------//File : test_bench.v//Author : cs//Created : //Last modified : //-----------------------------------------------------------------------------//Description :-----------------------------------------------------------------------------//Copyright (c) by This model is the confidential and//proprietary property of and the possession or use of this//file requires a written license from .//------------------------------------------------------------------------------//Modification history :-----------------------------------------------------------------------------moduletestbench();regclk;regrst_n;regstart_en;reg [7:0] mul_cand_data;reg [7:0] mul_data;wiredone_flag;wire [15:0] mul_result;//------------------------------------------------------------------------------
multiplier u_multiplier(/*autoinst*/
//Outputs
.done_flag (done_flag),
.mul_result (mul_result[15:0]),//Inputs
.clk (clk),
.rst_n (rst_n),
.start_en (start_en),
.mul_cand_data (mul_cand_data[7:0]),
.mul_data (mul_data[7:0]));always #20 clk = ~clk;initial
beginclk= 0;
rst_n= 0;
#100rst_n= 1;end
reg [3:0] i;always@(posedge clk or negedge rst_n)begin
if(rst_n==0)beginstart_en<= 0;
mul_cand_data<= 0;
mul_data<= 0;
i<= 0;end
else
case(i)0:begin
if(done_flag)beginstart_en= 0;
i<= i + 1'b1;
end
else beginstart_en<= 1'b1;
mul_cand_data <= 8'd5;
mul_data <= 8'd8;
end
end //case: 0
1:begin
if(done_flag)beginstart_en= 0;
i<= i + 1'b1;
end
else beginstart_en<= 1'b1;
mul_cand_data <= 8'b11111100;
mul_data <= 8'd4;
end
end //case: 1
2:begin
if(done_flag)beginstart_en= 0;
i<= i + 1'b1;
end
else beginstart_en<= 1'b1;
mul_cand_data <= 8'd127;
mul_data <= 8'b10000001;
end
end //case: 2
3:begin
if(done_flag)beginstart_en= 0;
i<= i + 1'b1;
end
else beginstart_en<= 1'b1;
mul_cand_data <= 8'b10000001;
mul_data <= 8'b10000001;
end
end //case: 3
4:begini<=4'd4;
mul_cand_data <= 0;
mul_data <= 0;
end
endcase //case (i)
end //always@ (posedge clk or negedge rst_n)
initial
begin$fsdbDumpfile ("./testbench.fsdb");
$fsdbDumpvars;// end
endmodule
仿真结果
2015年4月9日
cslegend