在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 4413|回复: 7

[讨论] 分享一点设计技巧:LDM指令如何多周期处理

[复制链接]
发表于 2012-4-24 12:59:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
我们看arm的架构体系,比较麻烦的是LDM指令。LDM指令是这样的,32位指令的低16bit会对应寄存器组的R0~R15。某一个bit设定为1,那么该bit对应的寄存器会作为目标寄存器,把数据从RAM内读出,写入该寄存器。但是哪一个bit是1还是0,这是随机的。如果我们处理这条LDM指令,自然是从低位到高位,1 bit占据一个周期进行处理,然后该bit复位为0,直到所有的bit全部变为0。

  现在问题出来了,cmd[15:0]如何完成这样的操作呢?它的16个bit每一个bit都可能是1,我们如何能够让它从低位到高位,不断的从1变成0,直到所有的1全部变成0?如果把cmd[15:0]当成一个整体考虑,那么我们无论如何是无法完成这个操作的。因为cmd[15:0]每一bit是0是1的情况有2^16种,难道我们要穷举出来?

  可能很多人在尝试做ARM处理器实现的时候,都会碰到这个拦路虎,无法对全功能指令进行处理。现在verilog描述技巧派上了用场。看下面,对cmd的描述代码:



  1. always @ ( posedge clk or posedge rst )
  2. if ( rst )
  3.     cmd <= #`DEL 32'd0;
  4. else if ( cpu_en )
  5.     if ( ~hold_en )
  6.             cmd <= #`DEL  code;
  7.         else if ( cmd_is_swp ) begin
  8.             cmd[27:25] <= #`DEL 3'b110;
  9.                 cmd[15:12] <= #`DEL cmd[3:0];
  10.                 end
  11.         else if ( cmd_is_multl )
  12.             cmd[27:25] <= #`DEL 3'b110;          
  13.     else if ( cmd_is_ldm ) begin
  14.             cmd[0] <= #`DEL 1'b0;
  15.                 cmd[1] <= #`DEL cmd[0] ? cmd[1] : 1'b0;
  16.                 cmd[2] <= #`DEL (|(cmd[1:0])) ? cmd[2] : 1'b0;
  17.                 cmd[3] <= #`DEL (|(cmd[2:0])) ? cmd[3] : 1'b0;               
  18.                 cmd[4] <= #`DEL (|(cmd[3:0])) ? cmd[4] : 1'b0;
  19.                 cmd[5] <= #`DEL (|(cmd[4:0])) ? cmd[5] : 1'b0;       
  20.                 cmd[6] <= #`DEL (|(cmd[5:0])) ? cmd[6] : 1'b0;
  21.                 cmd[7] <= #`DEL (|(cmd[6:0])) ? cmd[7] : 1'b0;               
  22.                 cmd[8] <= #`DEL (|(cmd[7:0])) ? cmd[8] : 1'b0;
  23.                 cmd[9] <= #`DEL (|(cmd[8:0])) ? cmd[9] : 1'b0;       
  24.                 cmd[10] <= #`DEL (|(cmd[9:0])) ? cmd[10] : 1'b0;       
  25.                 cmd[11] <= #`DEL (|(cmd[10:0])) ? cmd[11] : 1'b0;            
  26.                 cmd[12] <= #`DEL (|(cmd[11:0])) ? cmd[12] : 1'b0;         
  27.                 cmd[13] <= #`DEL (|(cmd[12:0])) ? cmd[13] : 1'b0;       
  28.                 cmd[14] <= #`DEL (|(cmd[13:0])) ? cmd[14] : 1'b0;         
  29.                 cmd[15] <= #`DEL (|(cmd[14:0])) ? cmd[15] : 1'b0;                        
  30.         end       
  31.         else;
  32. else;



复制代码
在认定cmd是LDM指令后,也就是cmd_is_ldm生效后,我们就必须从cmd[0]开始不断的把1变成0,直到最后一个1。在上面的实现代码中,我们不是吧cmd[15:0]作为整体考虑,而是对每一个bit作为个体考虑,那么各个击破,就达到了目标。

   以cmd[0]来说,不管cmd[0]是0还是1,那么下一个周期它必然等于0。
  以cmd[1]来说,它要看cmd[0]是否等于1,如果cmd[0]等于1,那么这一周期轮不上cmd[1]从1变成0,它可以保持不变;如果cmd[1]等于0,那么对不起,cmd[1]也会不管等于啥,都必须等于0。
  以cmd[2]来说,它要看的对象是cmd[1:0]中间是否含有一个1,只有cmd[2]前面有一个1存在,那么cmd[2]就可以保持不变,没有它的事,有前面的bit顶着呢;如果cmd[1:0]全部等于0,那么cmd[2]也就必须强制等于0。
   以此类推,cmd[15:3]都可以采用这个方法描述。

  那么,不管cmd[15:0]是何种bit图案,那么cmd[15:0]都会从低到高的把1电平变成0电平。

  LDM指令的cmd[15:0]含有几个1,那么cmd[15:0]也就会有几个周期来变成全0,因此我们就实现了对LDM指令的分化,我们只要对每一个周期的最低bit进行处理,完成单周期的LDR操作即可。
发表于 2012-4-24 13:18:24 | 显示全部楼层
LZ 的对齐很好,是用哪个编辑器输入的,如果有大纲方式显示就更好了。
 楼主| 发表于 2012-4-24 13:49:31 | 显示全部楼层
我一般使用notepad++,很好用。还有一点好用的是选中某个变量,其他地方用到这个变量的都会高亮。
发表于 2014-11-7 15:39:21 | 显示全部楼层
楼主厉害的
发表于 2014-11-12 09:20:33 | 显示全部楼层
高人!
发表于 2014-11-18 15:49:02 | 显示全部楼层
楼主厉害!
发表于 2014-11-18 23:04:10 | 显示全部楼层
楼主厉害
发表于 2019-6-9 16:12:41 | 显示全部楼层

楼主厉害
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-3-29 05:04 , Processed in 0.026508 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表