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

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

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3349|回复: 9

开源软核学习笔记07(学习《OPENMIPS开讲》)——2014_7_26

[复制链接]
发表于 2014-7-26 14:01:41 | 显示全部楼层 |阅读模式

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

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

x
学习背景:
    距离 第一遍学习 OPENmips 已经快半年了,当时连FPGA开发板都没摸过就开始学习,很多基础都不扎实。现在又有了些 FPGA开发板使用基础,正好 再来学习 OPENMIPS verilog版。

http://bbs.eetop.cn/thread-454236-1-1.html

************************

简单的回顾,

首先,这次学习不是 从一穷二白开始的,已经有了学习 笔记4 和笔记5 来辅助。


                               
登录/注册后可看大图


当时,笔记4 中对 OPENMIPS 模型(ORI 指令的实现)的理解。

因为leishangwen 采用的是增量 写作方式,模型逐步增加,


day4-2流水线.gif
day 4-2

。。。

day6流水线.gif

day 6

。。。。
day9流水线.gif



day 9

*****************

省略了中间很多图,同时 也进行了 修改,在增量的基础上,改为了 在 day-3 基础上每次 只更改一两个功能,而不是 逐步累加。

热身后,就可以开始了。
 楼主| 发表于 2014-7-26 14:38:19 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-7-27 17:37 编辑

*************第4章 第一条指令ori的实现

取指阶段的实现
**************

参考资料,http://blog.csdn.net/leishangwen/article/details/38082871
因为学习笔记只是辅助理解,所以有些不影响理解的细节会省略。


取指阶段取出指令存储器中的指令,同时,PC值递增,准备取下一条指令,包括PC、IF/ID两个模块。

01.JPG

pc 模块简略如上

使用了 <=,顺便向下看了其他模块,都是 <=,非阻塞赋值。
目前,感觉理解 <= 比较好的资料,如下
02.JPG


然后,理解很简单,引用一下

在复位的时候,输出的指令存储器使能信号为ChipDisable,表示指令存储器禁用,其余时刻指令存储器使能信号为ChipEnable,表示指令存储器使能。

      当指令存储器禁用时,PC的值保持为0,当指令存储器使能时,PC的值会在每时钟周期加4,表示下一条指令的地址,因为一条指令是32位,而我们设计的OpenMIPS是可以按照字节寻址,一条指令对应4个字节,所以PC加4指向下一条指令地址。


**************************

IF/ID模块的作用是暂时保存取指阶段取得的指令,以及对应的指令地址,并在下一个时钟传递到译码阶段。


if 应该是 interface fetch

id 应该是 interface decode


03.JPG



VERILOG版本 好像 没有提到 IMEM。
 楼主| 发表于 2014-7-26 15:35:14 | 显示全部楼层
***************2 译码阶段的实现***************

先 回顾一下,当时VHDL版本的实现,

                               
登录/注册后可看大图



采用模块化结构,学习思路 就容易了。

译码阶段包括Regfile、ID和ID/EX三个模块。


首先 看REGFILE,对比了一下代码,VHDL 版本和 VERILOG 版本接口一致,非常好,能省不少力气。


唯一有疑惑的地方,
注意一点:读寄存器操作是组合逻辑电路,也就是一旦输入的要读取的寄存器地址raddr1或者raddr2发生变化,那么会立即给出新地址对应的寄存器的值,这样可以保证在译码阶段取得要读取的寄存器的值,而写寄存器操作是时序逻辑电路,写操作发生在时钟信号的上升沿。


rdata1 <= regs[raddr1];


读操作 也应该是 时序 逻辑电路,虽然 regs[raddr1] 是当前地址下 的寄存器的值。

***************

ID 模块有些复杂,还好可以 借助VHDL版来理解,

04.JPG


上图,没有体现出 立即数 的作用,

  • end else
    if(reg1_read_o == 1'b1) begin  
  •     reg1_o <= reg1_data_i;   // Regfile读端口1的输出值
  • end else
    if(reg1_read_o == 1'b0) begin  
  •     reg1_o <= imm;           // 立即数

   代码片段如上,理解 reg1_o 有几种选择即可。


****************


ID/EX 模块 与 原来的不一样。


VHDL 版只有 ID/EX 模块,而 VERILOG 版 分成了 ID 模块 和 ID/EX 模块。




需要理解一下。
 楼主| 发表于 2014-7-27 15:52:05 | 显示全部楼层
**************好像多了一级流水
ID + ID/EX
**************

05.JPG
   

不理解 为什么把 ID/EX 分成了 ID + ID/EX,这样就多了一级流水。

只看 ID/EX 代码,没有复杂运算,完全可以把 ID + ID/EX 都合并到 ID/EX模块中,感觉ID模块没有必要单独存在。
  •     always @ (posedge clk) begin  
  •       if (rst == `RstEnable) begin  
  •         ex_aluop  <= `EXE_NOP_OP;  
  •         ex_alusel <= `EXE_RES_NOP;  
  •         ex_reg1   <= `ZeroWord;  
  •         ex_reg2   <= `ZeroWord;  
  •         ex_wd     <= `NOPRegAddr;  
  •         ex_wreg   <= `WriteDisable;  
  •       end else begin         
  •         ex_aluop  <= id_aluop;  
  •         ex_alusel <= id_alusel;  
  •         ex_reg1   <= id_reg1;  
  •         ex_reg2   <= id_reg2;  
  •         ex_wd     <= id_wd;  
  •         ex_wreg   <= id_wreg;  
  •       end
 楼主| 发表于 2014-7-27 17:08:41 | 显示全部楼层
*****************ID 指令 的理解
*****************

因为 只学第一个 ORI 命令,是

I-TYPE,ORI 中 的 I 就是 imm 立即数。

06.JPG

相应的

  // 对于ori指令只需通过判断第26-31bit的值,即可判断是否是ori指令  
  wire[5:0] op  = inst_i[31:26];

然后,

    wd_o        <= inst_i[15:11];
    reg1_addr_o <= inst_i[25:21];  // 默认通过Regfile读端口1读取的寄存器地址  
    reg2_addr_o <= inst_i[20:16];  // 默认通过Regfile读端口2读取的寄存器地址  


inst_i 全身都是宝,每一部分都有效利用了。

核心是下面的运算,
case (op)  
      `EXE_ORI: begin                // 依据op的值判断是否是ori指令  

            // ori指令需要将结果写入目的寄存器,所以wreg_o为WriteEnable  
         wreg_o      <= `WriteEnable;   

            // 运算的子类型是逻辑“或”运算  
            aluop_o     <= `EXE_OR_OP;  

            // 运算类型是逻辑运算  
         alusel_o    <= `EXE_RES_LOGIC;   

           // 需要通过Regfile的读端口1读取寄存器  
           reg1_read_o <= 1'b1;  

           // 不需要通过Regfile的读端口2读取寄存器  
           reg2_read_o <= 1'b0;  

           // 指令执行需要的立即数  
           imm         <= {16'h0, inst_i[15:0]};   

           // 指令执行要写的目的寄存器地址  
           wd_o        <= inst_i[20:16];   

           // ori指令是有效指令  
         instvalid   <= `InstValid;  

       end   


07.JPG

end else if(reg2_read_o == 1'b1) begin  
    reg2_o <= reg2_data_i;   // Regfile读端口2的输出值  
end else if(reg2_read_o == 1'b0) begin  
    reg2_o <= imm;           // 立即数  

有意思的是,立即数 是通过 REG2 来传递的。并没有单独为立即数 建立一个寄存器。

引用一下原文解释,
结合对Regfile模块的介绍可知,译码阶段会读取寄存器rs的值。指令ori需要的另一个操作数是立即数,所以设置reg2_read_o为0,表示不通过Regfile读端口2读取寄存器,这里暗含使用立即数作为运算的操作数。imm就是指令中的立即数进行零扩展后的值。
 楼主| 发表于 2014-7-27 17:45:30 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-7-27 18:05 编辑

**************EX 模块 引发的 <=

还是 =

**************

先不看细节,同样的问题,

VHDL 版本的 EX/MEM 分为了 EX和 EX/MEM 两个模块。

然后 EX 模块也同样使用了 <= ,但是又解释 EX模块中都是组合逻辑电路


估计 是 笔误, EX 模块中的 <= 应该 都改为 =
这样就是 组合逻辑电路了。


同理,ID模块也一样,应该把 <= 改为 =。

*********************************************
再引用一个好的解释


http://zhidao.baidu.com/link?url=4AAdBRVntsBC-II8Os-RXH81NzYJPjIF7Yv55vD55Di4_ucT1zaaytnhv4P8Gf7H84oYur5EMxG20tM97TjsNK


VHDL语言里没有阻塞与非阻塞之分。相比Verilog,VHDL更适合行为级建模。
Verilog HDL中,有两种过程赋值方式,即阻塞赋值(blocking)和非阻塞赋值(nonblocking)。阻塞赋值执行时,RHS(right hand statement)估值与更新LHS(left hand statement)值一次执行完成,计算完毕,立即更新。在执行时阻塞同块中的其他语句的执行。阻塞式(blocking)的操作符为 “ = ”。它的执行很像传统程序设计语言。非阻塞赋值RHS估值与更新LHS值分两步执行。在单位仿真周期开始时RHS估值,在同一单位仿真周期末更新LHS值,不阻塞同块中其他语句的执行。非阻塞式(non-blocking)的操作符为 “ <= ”,它的执行更像并行电路,使描述电路更自然。阻塞赋值与非阻塞赋值是Verilog HDL程序设计的难点,它们既有共同点,也有差异,深入剖析其异同,对于硬件程序的开发具有重大意义。

设计原则:
&#376;         原则1:时序电路建模时,用非阻塞赋值。

&#376;         原则2:锁存器电路建模时,用非阻塞赋值。

&#376;         原则3:用always块写组合逻辑时,采用阻塞赋值。

&#376;         原则4:在同一个always块中同时建立时序和组合逻辑电路时,用非阻塞赋值。

&#376;         原则5:在同一个always块中不要同时使用非阻塞赋值和阻塞赋值。

&#376;         原则6:不要在多个always块中为同一个变量赋值。

&#376;         原则7:用$strobe系统任务来显示用非阻塞赋值的变量值

&#376;         原则8:在赋值时不要使用 #0 延迟
 楼主| 发表于 2014-7-28 11:58:18 | 显示全部楼层
****************= ID 和 EX 模块后
****************

把 这两个模块 都改为 = ,即 组合逻辑电路后,


08.JPG

09.JPG
   
就容易理解了,基本上 和 VHDL 版本思路一致。
发表于 2014-7-28 13:45:36 | 显示全部楼层
回复 4# oldbeginner


    ID、ID/EX分开,是由于前者是组合逻辑,后者是时序逻辑,实现寄存器
发表于 2014-7-28 13:46:52 | 显示全部楼层
回复 6# oldbeginner


    综合器一般会自动识别的
 楼主| 发表于 2014-7-28 15:23:52 | 显示全部楼层
回复 8# leishangwen

这个现在理解了。感觉最好还是用 = ,不要用<=。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

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

GMT+8, 2024-5-7 06:01 , Processed in 0.036261 second(s), 9 queries , Gzip On, Redis On.

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