微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 跟我写ARM处理器之二:主体结构的确定

跟我写ARM处理器之二:主体结构的确定

时间:11-10 来源:互联网 点击:
好了,上一节定义了端口,基本功能大慨大家已经了然于胸了,现在来确定一下主体结构。我举几个指令执行的例子吧。

第一个是MLA R1,R2,R3,R0。它的意思是:R1=R2*R3 + R0。如果我们要实现这一条指令的话,一个32×32的乘法器需要,一个32+32的加法器是跑不了的。现在定义几个节点:Rm = R2; Rs=R3; sec_operand(第二操作数的意思)=mult_rm_rs[31:0](mult_rm_rs的低32位);Rn=R0;则结果等于:Rn + sec_operand。

第二个是:SUB R1,R0, R2, LSL #2。它的意思是:R1=R0 - R2<2。看了我前面文章的知道,这个指令同样可以像前面一样套入:Rm=R2; Rs=32b100; sec_operand=mult_rm_rs[31:0];Rn=R0;结果等于:Rn - sec_operand。

第三个是:LDR R1,[R0,R2,LSR #2]!。这是一条取RAM的数据进入寄存器的指令,取地址是:R0+R2>>2。并把取地址保存回R0。现在比较难计算的是: R0+R2>>2。但是这个同样也可以往前两个模式一样靠:Rm=R2; Rs=32b0100_0000_0000_0000_0000_0000_0000_0000,那么sec_operand = mult_rm_rs[63:32]正好等于:R2>>2。如果Rn=R0,取地址就等于:Rn+sec_operand。这个地址还要送入R0中。

看到这,大家明白了本核的核心结构了吧。网友先别赞我眼光如炬,目光如神,一眼看出核心所在。实际上我在写第一版的时候,绝没想到把移位交给乘法器来完成,也是傻傻地参考别人文档写了一个桶形移位器。但后来灵光一现,觉得既然乘法器避免不了,如果只让他在MUL指令的时候使用,其他指令的时候闲着,那多么没意思呀。这样乘法器复用起来,让它参与了大部分指令运算。

好了,我们要做的事是这样的。指令到来,准备Rm, Rs, Rn,为生成sec_operand产生控制信号,决定Rn和sec_operand之间是加还是减,那么最后生成的结果要么送入寄存器组,要么作为地址参与读写操作。就这么简单!

前面的这一套完成了,我想ARM核也就成功了大半了。

上面解决了做什么的问题,随之而来的是怎么做的问题。可能大家首先想到的是三级流水线。为什么是三级呢?为什么不是两级呢?两级有什么不好?我告诉你们,两级同样可以,无非是关键路径长一点。我接下来,就要做两级,没有什么能束缚我们!实际上,很多项目用不到30、40MHz的速度,10M,20M也是可以接受,100ns,50ns内,我那一套乘加结构同样能满足。口说无凭,看看我代码中是如何生成:Rm,Rs, sec_operand,Rn的:

注:以下非正式代码,讲解举例所用

/*

always @ ( * )

if ( code_is_ldrh1|code_is_ldrsb1|code_is_ldrsh1 )

code_rm ={code[11:7],code[3:0]};

else if ( code_is_b )

code_rm ={{6{code[23]}},code[23:0],2b0};

else if ( code_is_ldm )

case( code[24:23] )

2d0 : code_rm ={(code_sum_m - 1b1),2b0};

2d1 : code_rm =0;

2d2 : code_rm ={code_sum_m,2b0};

2d3 : code_rm =3b100;

endcase

else if ( code_is_swp )

code_rm =0;

else if ( code_is_ldr0 )

code_rm =code[11:0];

else if ( code_is_msr1|code_is_dp2 )

code_rm =code[7:0];

else if ( code_is_multl & code[22] & code_rma[31] )

code_rm =~code_rma + 1b1;

else if ( ( (code[6:5]==2b10) & code_rma[31] ) & (code_is_dp0|code_is_dp1|code_is_ldr1))

code_rm =~code_rma;

else

code_rm =code_rma;

always @ ( * )

case ( code[3:0] )

4h0 : code_rma =r0;

4h1 : code_rma =r1;

4h2 : code_rma =r2;

4h3 : code_rma =r3;

4h4 : code_rma =r4;

4h5 : code_rma =r5;

4h6 : code_rma =r6;

4h7 : code_rma =r7;

4h8 : code_rma =r8;

4h9 : code_rma =r9;

4ha : code_rma =ra;

4hb : code_rma =rb;

4hc : code_rma =rc;

4hd : code_rma =rd;

4he : code_rma =re;

4hf : code_rma =rf;

endcase

*/

我有if else这个法宝,你不管来什么指令,我都给你准备好Rm。这就像一台脱粒机,你只要在送货口送东西即可。你送麦子脱麦子,你送玉米脱玉米。你的Rm来自于寄存器组,那好我用code_rma来给你选中,送入Rm这个送货口。你的Rm来自代码,就是一套立即数,那我就把code[11:0]送入Rm,下面的程式有了正确的输入,你只要把最后的正确结果,送给寄存器组即可。

再看看Rs的生成:

注:以下非正式代码,讲解举例所用

/*

always @ ( * )

if ( code_is_dp0|code_is_ldr1 )

code_rot_num =( code[6:5] == 2b00 ) ? code[11:7] : ( ~code[11:7]+1b1 );

else if ( code_is_dp1 )

code_rot_num =( code[6:5] == 2b00 ) ? code_rsa[4:0] : ( ~code_rsa[4:0]+1b1 );

else if ( code_is_msr1|code_is_dp2 )

code_rot_num ={ (~code[11:8]+1b1),1b0 };

else

code_rot_num =5b0;

always @ ( * )

if ( code_is_multl )

if ( code[22] & code_rsa[31] )

code_rs =~code_rsa + 1b1;

else

code_rs =code_rsa;

e

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top