cpu设计报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Z1
Z0
以下是带符号数乘法器的代码,其中前半部分用与非门实现,后半部分经过逻辑综合后得到结果。
modulemul_signed(a,b,z);
input[15:0]a,b;
output[31:0] z;
reg[15:0]a_bi[15:0];
integeri,j;
always@ * begin
for(i=0;i<15;i=i+1)
+p[i]p[i-1]g[i-2]
+……
+p[i]p[i-1]……p[1]c[0]
+ p[i]p[i-1]……p[1]p[0]c[0]
从理论上来讲,由c[i+1]的表达式可以并行产生所有位的进位输入,但是这样的电路太复杂,难以实现。所以采用了树形结构来分层次产生进位。
首先是一位加法器的代码,除了产生一位加法结果s外,还生成进位产生的函数g和进位传递函数p。一位加法器和GP生成器代码如下:
modulecla_2 (a,b,c_in,g_out,p_out,s);
input[1:0]a,b;
inputc_in;
outputg_out,p_out;
output[1:0] s;
wire[1:0]g,p;
wirec_out;
add add0 (a[0],b[0],c_in, g[0],p[0],s[0]);
endmodule
六、指令系统
本CPU部分指令如下(有一些是我自己用来调试的指令,在此就不列举了):
000000
Rs
rt
rd
00000
100000
寄存器加
000000
Rs
Rt
Rd
00000
100010
寄存器减
000000
Rs
Rt
Rd
00000
100100
寄存器与
000000
Rs
Rt
Rd
00000
100101
(({12'b0,a_bi[4][15],a_bi[4][14:0], 4'b0}+
{11'b0,a_bi[5][15],a_bi[5][14:0], 5'b0})+
({10'b0,a_bi[6][15],a_bi[6][14:0], 6'b0}+
{9'b0,a_bi[7][15],a_bi[7][14:0], 7'b0}))+
moduleadd (a,b,c,g,p,s);
inputa,b,c;
outputg,p,s;
assigns =a^b^c;
assigng =a&b;
assignp =a|b;
endmodule
moduleg_p(g,p,c_in,g_out,p_out,c_out);
input[1:0]g,p;
inputc_in;
A
B
Ci
Co
S
计算式
0
0
0
0
0
0+ 0 + 0 = 0 0
0
0
1
0
1
0+ 0 +1= 01
0
1
0
0
1
0+1+ 0 = 01
0
1
1
1
0
0+1+1=10
1
0
0
0
1
1+ 0 + 0 = 01
1
0
1
1
0
1+ 0 +1=10
1
1
0
1
0
1+1+ 0 =10
1
1
1
1
1
1+1+1=1 1
moduleadd (a,b,ci,s,co);
for(j=0;j<15;j=j+1)
a_bi[i][j] = a[i] &b[j];
for(i=0;i<15;i=i+1)
a_bi[i][15] = ~(a[i]&b[15]);
for(j=0;j<15;j=j+1)
a_bi[15][j] = ~(a[15]&b[j]);
a_bi[15][15] = a[15] & b[15];
modulecla32 (a,b,ci,s,co);
input[31:0]a,b;
inputci;
output[31:0] s;
outputco;
wireg_out,p_out;
cla_32cla(a,b,ci,g_out,p_out,s);
assignco =g_out|p_out& ci;
endmodule
a)当S=00时,y=a0;
b)当S=01时,y=a1;
c)当S=10时,y=a2;
d)当S=11时,y=a3;
modulemux4x32 (a0,a1,a2,a3,s,y);
input[31:0] a0,a1,a2,a3;
input[1:0] s;
output[31:0] y;
function[31:0] select;
二、多路选择器设计
本CPU共用到了32位的二选一多路选择器,四选一多路选择器以及八选一多路选择器。思路大致相同,已四选一多路选择器为例来简单介绍,其他两个多路选择器与其结构差异不大。
以下是四选一多路选择器的代码,其中a0,a1,a2,a3是32位的输入信号,y为32位的输出信号。S为两位的选择信号:
end
assignz = (({16'b1,a_bi[0][15],a_bi[0][14:0]}+
{15'b0,a_bi[1][15],a_bi[1][14:0], 1'b0})+
({14'b0,a_bi[2][15],a_bi[2][14:0], 2'b0}+
{13'b0,a_bi[3][15],a_bi[3][14:0], 3'b0}))+
immediate
立即数加
001100
Rs
Rt
Immediate
立即数加
001101
Rs
Rt
Immediate
立即数加
001110
Rs
Rt
Immediate
立即数加
100011
Rs
Rt
Offset取整数数据字10来自011RsRt
Offset
存整数数据字
111111
全0
停机指令
000011
address
sh= d >>sa;
endelse begin
sh= $signed(d) >>>sa;
end
end
endmodule
四、加法器设计
本加法器使用补码运算,所以支持减法操作。因为使用补码时:做加减法运算时与无符号数是相同的。
首先考虑一位二进制数的相加,能够完成一位二进制数加法的电路称为半加器,当把低位的进位考虑进来后,就产生了全加器。以下是全加器的真值表,我们可以根据真值表来写出电路的功能描述风格的代码。
(({8'b0,a_bi[8][15],a_bi[8][14:0], 8'b0}+
{7'b0,a_bi[9][15],a_bi[9][14:0], 9'b0})+
({6'b0,a_bi[10][15],a_bi[10][14:0],10'b0}+
{5'b0,a_bi[11][15],a_bi[11][14:0],11'b0}))+
试验报告——cpu设计
一、概述
我所设计的CPU与教员所给的要求存在不同,指令是32位的,寄存器和存储器均是32位的。设计思路是先写出CPU所需要的部件,然后设计指令系统,最后将各个部件按照指令集所生成的控制电路连接在一起。
这样做的好处是可以模块化的添加功能,比如:当CPU需要执行除法时,只需要设计除法器以及除法指令即可。缺点是各个功能模块之间的通信需要大量的控制信号,这些控制信号需要严格遵守制定好的指令集真值表,否则会出现大量错误,本人有切身体会,具体问题会在后面章节详细展开。
input[31:0] a0,a1,a2,a3;
input[1:0] s;
case(s)
2'b00: select = a0;
2'b01: select = a1;
2'b10: select = a2;
2'b11: select = a3;
endcase
endfunction
assigny = select(a0,a1,a2,a3,s);
outputg_out,p_out,c_out;
assigng_out= g[1] | p[1] & g[0];
assignp_out= p[1] & p[0];
assignc_out= g[0] | p[0] &c_in;
endmodule
有了以上两个模块,就可以设计一个两位先行加法器了。它使用了两个一位加法器和一个GP生成器。
(({4'b0,a_bi[12][15],a_bi[12][14:0],12'b0}+
{3'b0,a_bi[13][15],a_bi[13][14:0],13'b0})+
({2'b0,a_bi[14][15],a_bi[14][14:0],14'b0}+
{1'b1,a_bi[15][15],a_bi[15][14:0],15'b0}));
写成二进制的形式:
(-a3)×B3=0 0a3b2a3b1a3b0
(-b3)×A3=0 0a2b3a1b3a0b3
由于是反码,所以 ,对着两项同时取反加1后再相加,得:
7
6
5
4
3
1
1
a3b2
a3b1
a3b0
1
1
a2b3
a1b3
a0b3
0
0
0
0
1
+
0
0
0
0
1
化简后得:
7
6
5
4
3
0
0
a3b2
a3b1
a3b0
其中i的范围位0~2,A3和B3是无符号数。
由于(a+b)(x+y)=ax + ay +bx+ by,则Z8= A4× B4=(- a3× 23+ A3)×(- b3× 23+ B3)= a3× b3× 26+(- a3× B3× 23)+(- b3× A3× 23)+A3× B3。其中第一项与第四项与无符号数乘相同,而第二项和第三项为负。如下图所示:
0
0
a2b3
a1b3
a0b3
+
1
0
0
0
1
只需要把两个红色的1放在合适的位置即可,再把所有乘积项相加,就可得到带符号数的相乘结果。
7
6
5
4
3
2
1
0
1
a3b0
a2b0
a1b0
a0b0
a3b1
a2b1
a1b1
a0b1
a3b2
a2b2
a1b2
a0b2
1
a3b3
a2b3
a1b3
a0b3
Z7
Z6
Z5
Z4
Z3
Z2
调用
七、ALU设计
ALU是负责运算的电路。综合指令表可以看出,ALU需要实现以下运算:加法,减法,与运算,或运算,异或运算,左移,逻辑右移,算数右移,乘法运算。
endmodule
三、位移器设计
32位移位器对32为二进制数左移或者右移,移动位数可在0~31之间自由选择,右移时可选择逻辑右移(最高位填0)或者算数右移(高位符号扩展)。
以下是32位移位器的代码,d是32位输入信号,sh是32位输出信号,sa是5位移位位数控制信号,right是右移控制信号,arith是算数右移控制引号。
c[i+1] = a[i]b[i] + a[i]c[i] +b[i]c[i]
= a[i]b[i] + (a[i] + b[i]) c[i]
= g[i] + p[i]c[i]
其中g[i] = a[i]b[i]称为进位产生函数,p[i] = a[i] + b[i]称为进位传递函数,则
c[i+1] = g[i] + p[i]g[i-1]
add add1 (a[1],b[1],c_out,g[1],p[1],s[1]);
g_pg_p0 (g,p,c_in,g_out,p_out,c_out);
endmodule
四位,八位,十六位,三十二位先行加法器代码与两位先行加法器类似,在此不再叙述,附件代码中已给出。
以下是32位先行加法器的最后代码,除了产生32位加法结果,他也产生最后的进位输出。代码如下:
inputa,b,ci;
outputs,co;
assigns = a ^ b ^ ci;
assignco = (a & b) |(b & ci) | (a & ci);
endmodule
可以将许多全加器组合在一起,就组成了32位的加法器。但是这样的加法器速度很慢,因为进位将从输入的ci逐位的传递到最高位的进位输出co,途中需要穿越32个全加器,我们知道,电路是有延迟的,这样的长途旅行是要花时间的。为了加快加法器的运算速度,必须向办法能尽快地产生每位的进位。由于:
五、乘法器设计
此乘法器是两个16位带符号数相乘,两个乘数和结果均使用补码表示。大致原理如下:
设有两个补码表示的4位带符号数A4和B4,,计算Z8= A4× B4:
A4= a3a2a1a0= - a3× 23+ ∑ai× 2i= - a3× 23+ A3
B4= b3b2b1b0= -b3× 23+ ∑bi× 2i= - b3× 23+ B3
寄存器或
000000
Rs
Rt
Rd
00000
100110
寄存器异或
000000
Rs
Rt
Rd
00000
100111
寄存器乘
000000
000000
Rt
Rd
Sa
000000
左移
000000
000000
Rt
Rd
Sa
000010
逻辑右移
000000
000000
Rt
Rd
sa
000011
算数友谊
001000
Rs
Rt
moduleshift(d,sa,right,arith,sh);
input[31:0] d;
input[4:0]sa;
inputright,arith;
output[31:0]sh;
reg[31:0]sh;
always@* begin
if(!right) begin
Z0
以下是带符号数乘法器的代码,其中前半部分用与非门实现,后半部分经过逻辑综合后得到结果。
modulemul_signed(a,b,z);
input[15:0]a,b;
output[31:0] z;
reg[15:0]a_bi[15:0];
integeri,j;
always@ * begin
for(i=0;i<15;i=i+1)
+p[i]p[i-1]g[i-2]
+……
+p[i]p[i-1]……p[1]c[0]
+ p[i]p[i-1]……p[1]p[0]c[0]
从理论上来讲,由c[i+1]的表达式可以并行产生所有位的进位输入,但是这样的电路太复杂,难以实现。所以采用了树形结构来分层次产生进位。
首先是一位加法器的代码,除了产生一位加法结果s外,还生成进位产生的函数g和进位传递函数p。一位加法器和GP生成器代码如下:
modulecla_2 (a,b,c_in,g_out,p_out,s);
input[1:0]a,b;
inputc_in;
outputg_out,p_out;
output[1:0] s;
wire[1:0]g,p;
wirec_out;
add add0 (a[0],b[0],c_in, g[0],p[0],s[0]);
endmodule
六、指令系统
本CPU部分指令如下(有一些是我自己用来调试的指令,在此就不列举了):
000000
Rs
rt
rd
00000
100000
寄存器加
000000
Rs
Rt
Rd
00000
100010
寄存器减
000000
Rs
Rt
Rd
00000
100100
寄存器与
000000
Rs
Rt
Rd
00000
100101
(({12'b0,a_bi[4][15],a_bi[4][14:0], 4'b0}+
{11'b0,a_bi[5][15],a_bi[5][14:0], 5'b0})+
({10'b0,a_bi[6][15],a_bi[6][14:0], 6'b0}+
{9'b0,a_bi[7][15],a_bi[7][14:0], 7'b0}))+
moduleadd (a,b,c,g,p,s);
inputa,b,c;
outputg,p,s;
assigns =a^b^c;
assigng =a&b;
assignp =a|b;
endmodule
moduleg_p(g,p,c_in,g_out,p_out,c_out);
input[1:0]g,p;
inputc_in;
A
B
Ci
Co
S
计算式
0
0
0
0
0
0+ 0 + 0 = 0 0
0
0
1
0
1
0+ 0 +1= 01
0
1
0
0
1
0+1+ 0 = 01
0
1
1
1
0
0+1+1=10
1
0
0
0
1
1+ 0 + 0 = 01
1
0
1
1
0
1+ 0 +1=10
1
1
0
1
0
1+1+ 0 =10
1
1
1
1
1
1+1+1=1 1
moduleadd (a,b,ci,s,co);
for(j=0;j<15;j=j+1)
a_bi[i][j] = a[i] &b[j];
for(i=0;i<15;i=i+1)
a_bi[i][15] = ~(a[i]&b[15]);
for(j=0;j<15;j=j+1)
a_bi[15][j] = ~(a[15]&b[j]);
a_bi[15][15] = a[15] & b[15];
modulecla32 (a,b,ci,s,co);
input[31:0]a,b;
inputci;
output[31:0] s;
outputco;
wireg_out,p_out;
cla_32cla(a,b,ci,g_out,p_out,s);
assignco =g_out|p_out& ci;
endmodule
a)当S=00时,y=a0;
b)当S=01时,y=a1;
c)当S=10时,y=a2;
d)当S=11时,y=a3;
modulemux4x32 (a0,a1,a2,a3,s,y);
input[31:0] a0,a1,a2,a3;
input[1:0] s;
output[31:0] y;
function[31:0] select;
二、多路选择器设计
本CPU共用到了32位的二选一多路选择器,四选一多路选择器以及八选一多路选择器。思路大致相同,已四选一多路选择器为例来简单介绍,其他两个多路选择器与其结构差异不大。
以下是四选一多路选择器的代码,其中a0,a1,a2,a3是32位的输入信号,y为32位的输出信号。S为两位的选择信号:
end
assignz = (({16'b1,a_bi[0][15],a_bi[0][14:0]}+
{15'b0,a_bi[1][15],a_bi[1][14:0], 1'b0})+
({14'b0,a_bi[2][15],a_bi[2][14:0], 2'b0}+
{13'b0,a_bi[3][15],a_bi[3][14:0], 3'b0}))+
immediate
立即数加
001100
Rs
Rt
Immediate
立即数加
001101
Rs
Rt
Immediate
立即数加
001110
Rs
Rt
Immediate
立即数加
100011
Rs
Rt
Offset取整数数据字10来自011RsRt
Offset
存整数数据字
111111
全0
停机指令
000011
address
sh= d >>sa;
endelse begin
sh= $signed(d) >>>sa;
end
end
endmodule
四、加法器设计
本加法器使用补码运算,所以支持减法操作。因为使用补码时:做加减法运算时与无符号数是相同的。
首先考虑一位二进制数的相加,能够完成一位二进制数加法的电路称为半加器,当把低位的进位考虑进来后,就产生了全加器。以下是全加器的真值表,我们可以根据真值表来写出电路的功能描述风格的代码。
(({8'b0,a_bi[8][15],a_bi[8][14:0], 8'b0}+
{7'b0,a_bi[9][15],a_bi[9][14:0], 9'b0})+
({6'b0,a_bi[10][15],a_bi[10][14:0],10'b0}+
{5'b0,a_bi[11][15],a_bi[11][14:0],11'b0}))+
试验报告——cpu设计
一、概述
我所设计的CPU与教员所给的要求存在不同,指令是32位的,寄存器和存储器均是32位的。设计思路是先写出CPU所需要的部件,然后设计指令系统,最后将各个部件按照指令集所生成的控制电路连接在一起。
这样做的好处是可以模块化的添加功能,比如:当CPU需要执行除法时,只需要设计除法器以及除法指令即可。缺点是各个功能模块之间的通信需要大量的控制信号,这些控制信号需要严格遵守制定好的指令集真值表,否则会出现大量错误,本人有切身体会,具体问题会在后面章节详细展开。
input[31:0] a0,a1,a2,a3;
input[1:0] s;
case(s)
2'b00: select = a0;
2'b01: select = a1;
2'b10: select = a2;
2'b11: select = a3;
endcase
endfunction
assigny = select(a0,a1,a2,a3,s);
outputg_out,p_out,c_out;
assigng_out= g[1] | p[1] & g[0];
assignp_out= p[1] & p[0];
assignc_out= g[0] | p[0] &c_in;
endmodule
有了以上两个模块,就可以设计一个两位先行加法器了。它使用了两个一位加法器和一个GP生成器。
(({4'b0,a_bi[12][15],a_bi[12][14:0],12'b0}+
{3'b0,a_bi[13][15],a_bi[13][14:0],13'b0})+
({2'b0,a_bi[14][15],a_bi[14][14:0],14'b0}+
{1'b1,a_bi[15][15],a_bi[15][14:0],15'b0}));
写成二进制的形式:
(-a3)×B3=0 0a3b2a3b1a3b0
(-b3)×A3=0 0a2b3a1b3a0b3
由于是反码,所以 ,对着两项同时取反加1后再相加,得:
7
6
5
4
3
1
1
a3b2
a3b1
a3b0
1
1
a2b3
a1b3
a0b3
0
0
0
0
1
+
0
0
0
0
1
化简后得:
7
6
5
4
3
0
0
a3b2
a3b1
a3b0
其中i的范围位0~2,A3和B3是无符号数。
由于(a+b)(x+y)=ax + ay +bx+ by,则Z8= A4× B4=(- a3× 23+ A3)×(- b3× 23+ B3)= a3× b3× 26+(- a3× B3× 23)+(- b3× A3× 23)+A3× B3。其中第一项与第四项与无符号数乘相同,而第二项和第三项为负。如下图所示:
0
0
a2b3
a1b3
a0b3
+
1
0
0
0
1
只需要把两个红色的1放在合适的位置即可,再把所有乘积项相加,就可得到带符号数的相乘结果。
7
6
5
4
3
2
1
0
1
a3b0
a2b0
a1b0
a0b0
a3b1
a2b1
a1b1
a0b1
a3b2
a2b2
a1b2
a0b2
1
a3b3
a2b3
a1b3
a0b3
Z7
Z6
Z5
Z4
Z3
Z2
调用
七、ALU设计
ALU是负责运算的电路。综合指令表可以看出,ALU需要实现以下运算:加法,减法,与运算,或运算,异或运算,左移,逻辑右移,算数右移,乘法运算。
endmodule
三、位移器设计
32位移位器对32为二进制数左移或者右移,移动位数可在0~31之间自由选择,右移时可选择逻辑右移(最高位填0)或者算数右移(高位符号扩展)。
以下是32位移位器的代码,d是32位输入信号,sh是32位输出信号,sa是5位移位位数控制信号,right是右移控制信号,arith是算数右移控制引号。
c[i+1] = a[i]b[i] + a[i]c[i] +b[i]c[i]
= a[i]b[i] + (a[i] + b[i]) c[i]
= g[i] + p[i]c[i]
其中g[i] = a[i]b[i]称为进位产生函数,p[i] = a[i] + b[i]称为进位传递函数,则
c[i+1] = g[i] + p[i]g[i-1]
add add1 (a[1],b[1],c_out,g[1],p[1],s[1]);
g_pg_p0 (g,p,c_in,g_out,p_out,c_out);
endmodule
四位,八位,十六位,三十二位先行加法器代码与两位先行加法器类似,在此不再叙述,附件代码中已给出。
以下是32位先行加法器的最后代码,除了产生32位加法结果,他也产生最后的进位输出。代码如下:
inputa,b,ci;
outputs,co;
assigns = a ^ b ^ ci;
assignco = (a & b) |(b & ci) | (a & ci);
endmodule
可以将许多全加器组合在一起,就组成了32位的加法器。但是这样的加法器速度很慢,因为进位将从输入的ci逐位的传递到最高位的进位输出co,途中需要穿越32个全加器,我们知道,电路是有延迟的,这样的长途旅行是要花时间的。为了加快加法器的运算速度,必须向办法能尽快地产生每位的进位。由于:
五、乘法器设计
此乘法器是两个16位带符号数相乘,两个乘数和结果均使用补码表示。大致原理如下:
设有两个补码表示的4位带符号数A4和B4,,计算Z8= A4× B4:
A4= a3a2a1a0= - a3× 23+ ∑ai× 2i= - a3× 23+ A3
B4= b3b2b1b0= -b3× 23+ ∑bi× 2i= - b3× 23+ B3
寄存器或
000000
Rs
Rt
Rd
00000
100110
寄存器异或
000000
Rs
Rt
Rd
00000
100111
寄存器乘
000000
000000
Rt
Rd
Sa
000000
左移
000000
000000
Rt
Rd
Sa
000010
逻辑右移
000000
000000
Rt
Rd
sa
000011
算数友谊
001000
Rs
Rt
moduleshift(d,sa,right,arith,sh);
input[31:0] d;
input[4:0]sa;
inputright,arith;
output[31:0]sh;
reg[31:0]sh;
always@* begin
if(!right) begin