计算机组成原理课程设计要求编写一个5级流水MIPS的CPU,其他的都可以根据《自己动手写CPU》完成,只有乘法指令要求使用booth原理,去年的时候在网上找了很久没有找到,所以自己仿着div除法模块写了个。
以下是本篇文章正文内容
一、booth模块分析与设计
32位补码(Booth)乘法器设计原理:先将操作数都转化为绝对值,即对有符号运算且操作数最高位为1的操作数做取反加一的操作,这样在计算的时候就可以都按照无符号数来设计,booth乘法过程参照《计算机组成原理》(唐朔飞)教材中定点运算的补码一位乘来做的,设计了65位的p空间模拟计算过程中的中间变量,高32位根据0、1位的值加x或减x。最后求得最终结果时,要根据是否为有符号计算来转换结果。如果为有符号数且两个操作数符号位不同,则结果需要取反加一,求得真实值补码。
根据上述原理,可以将booth模块分成三个状态,即开始、运算、结束,考虑到如果操作数有0的时候可以一步判断出积为0,所以加上一个乘数为0的状态,共四个状态。在乘法计算过程中,流水线会暂停。
booth模块内部状态转换图、booth乘法运算过程流程图如图。
二、booth模块接口描述
实现booth乘法运算。接口描述如下表:
序号 | 接口名 | 宽度(bit) | 输入/输出 | 作用 |
---|---|---|---|---|
1 | clk | 1 | 输入 | 时钟信号 |
2 | rst | 1 | 输入 | 复位信号,高电平有效 |
3 | signed_mul_i | 32 | 输入 | 是否是有符号乘法 |
4 | opdata1_i | 32 | 输入 | 乘法的操作数1 |
5 | opdata2_i | 32 | 输入 | 乘法的操作数2 |
6 | start_i | 32 | 输入 | 是否开始乘法运算 |
7 | ready_o | 1 | 输出 | 是否已经完成乘法运算 |
8 | result_o | 64 | 输出 | 乘法运算的结果 |
三、booth模块核心代码
(没有找到Verilog的代码块…)
`MulFree:begin
if(start_i == `MulStart) begin
if(opdata1_i == `ZeroWord||opdata2_i == `ZeroWord) begin
state <= `MulByZero;
end
else begin
state <= `MulOn;
cnt <= 6'b000000;
p = {`ZeroWord,data2_mult[31:0],1'b0};
end
end
else begin
ready_o <= `MulResultNotReady;
result_o <= {`ZeroWord,`ZeroWord};
end
end
`MulByZero: begin
p = {`ZeroWord,`ZeroWord,1'b0};
state <= `MulEnd;
end
`MulOn:begin
if(cnt != 6'b100000) begin
if(p[1:0] == 2'b01) begin
p = {p[64:33] + data1_mult,p[32:0]};
end
else if(p[1:0] == 2'b10) begin
p = {p[64:33] + data1_minus,p[32:0]};
end
else begin
end
p = {p[64],p[64:1]};
cnt <= cnt + 1;
end
else begin
if(p[1:0] == 2'b01) begin
p[64:33] = (p[64:33] + data1_mult);
end
else if(p[1:0] == 2'b10) begin
p[64:33] = (p[64:33] + data1_minus);
end
else begin
end
state <= `MulEnd;
cnt <= 6'b000000;
end
end
`MulEnd:begin
result_o = p[64:1];
if((opdata1_i[31] ^ opdata2_i[31] == 1'b1) && signed_mul_i == 1'b1 ) begin
result_o = ~result_o + 1;
end
ready_o <= `MulResultReady;
if(start_i == `MulStop) begin
state <= `MulFree;
ready_o <= `MulResultNotReady;
result_o <= {`ZeroWord,`ZeroWord};