房产网站关键词优化,商城网站开发企业,营销网站制作方法,秦皇岛市住房和城乡建设局网站在开篇#xff0c;还是请大家首先准备好本项目所用的源代码。如果已经下载了#xff0c;那就不用重复下载了。如果还没有下载#xff0c;那么#xff0c;请大家点击下方链接#xff0c;来了解下载本项目的CPU源代码的方法。
下载本项目代码
准备好了项目源代码以后…在开篇还是请大家首先准备好本项目所用的源代码。如果已经下载了那就不用重复下载了。如果还没有下载那么请大家点击下方链接来了解下载本项目的CPU源代码的方法。
下载本项目代码
准备好了项目源代码以后我们接着去讲解。
在之前的章节里我是讲解了使用Quartus II 13.1的IP核生成的功能来生成RAM IP核。讲完了这个以后我们在这一节接着来讲解取指令模块。
我还是将取指令模块的代码给整体地贴在下面。
module get_instruct
(input wire sys_clk,input wire sys_rst_n,input wire get_inst_en,input wire [15:0] ip,output reg decode_en,output reg [15:0] instruct_code
);reg [15:0] ip_buf;
wire [15:0] instruct_code_wire;reg rd_en;
reg rd_en_d1;
reg rd_en_d2;always (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n 1b0)ip_buf 16h0;else if (get_inst_en 1b1)ip_buf ip;elseip_buf ip_buf;always (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n 1b0)rd_en 1b0;else if (get_inst_en 1b1)rd_en 1b1;elserd_en 1b0;always (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n 1b0)beginrd_en_d1 1b0;rd_en_d2 1b0;endelsebeginrd_en_d1 rd_en;rd_en_d2 rd_en_d1;endalways (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n 1b0)begindecode_en 1b0;instruct_code 16h0;endelse if (rd_en_d1 1b1)begindecode_en 1b1;instruct_code instruct_code_wire;endelsebegindecode_en 1b0;instruct_code instruct_code;endram_disk_256x16 ram_disk_inst (.aclr ( ~sys_rst_n ),.address ( ip_buf ),.clock ( sys_clk ),.data ( 16hz ),.rden ( rd_en ),.wren ( 1b0 ),.q ( instruct_code_wire ));endmodule
上述代码块位于【\cpu_me01\code\get_instruct.v】里面。
一. ip_buf的非阻塞赋值
我们来看看关于ip_buf的非阻塞赋值代码块。 图1 由图1可以看到ip_buf在复位时它为0值。检测到输入信号中的【get_inst_en】为高电平以后ip_buf非阻塞赋值为输入信号【ip】的值。此后ip_buf保持此值不变。
在这里取指令使能信号【get_inst_en】它是来自于控制中心模块【ctrl_center】的。每次准备取指令时【get_inst_en】才会变为1且仅仅维持一个时钟周期的高电平。其余的时间里它为0值。
这样一来图1中的【ip_buf】它是说每检测到一次【get_inst_en】为高电平就缓存一次【ip】的值然后在【get_inst_en】为低电平期间【ip_buf】保持不变。下一次检测到一次【get_inst_en】为高电平的时候就缓存新的【ip】的值。逻辑不难。 二. rd_en的非阻塞赋值 图2 从图2来看读使能变量【rd_en】它在系统复位时为0值。当检测到控制中心传来的取指令使能信号【get_inst_en】变为高电平的时候读使能信号【rd_en】变为1。其余时间【rd_en】为0。
取指令使能我们讲了它是由控制中心模块传来的且仅仅维持一个时钟周期的高电平其余时间为0值。而【rd_en】其实也是一样的。【rd_en】的逻辑仅仅在检测到【get_inst_en】为1时【rd_en】才为1其余时候【rd_en】为0。而【get_inst_en】仅仅维持一个时钟周期所以【rd_en】的高电平也是仅仅维持一个时钟周期。
注意【ip_buf】与【rd_en】都是本地变量如下图所示。 图3 图3中的第12行和第15行可以表明【ip_buf】与【rd_en】均为本地变量。 三. 延时信号【rd_en_d1】与【rd_en_d2】
在图3中我们可以看到两个延时信号【rd_en_d1】与【rd_en_d2】。所谓的延时是对【rd_en】信号进行延时。在这里虽说我声明了两个延时信号但是实际用到的只有【rd_en_d1】而已。之所以要多申请一个是因为我担心一个延时信号不够用。
生活中好多事情我也是这样的。因为总担心东西会不够用所以我倾向于多准备一些。对于擅长精打细算的人来讲我这种做法可能会显得有些不好理解。
我们还是来看一看代码。 图4 我先来说一说代码的执行效果。效果就是【rd_en_d1】相比【rd_en】延后了1个时钟周期【rd_en_d2】又比【rd_en_d1】延后了1个时钟周期。
接下来我又会用文字说明的方法来演示这种代码执行过程了。请大家先将图4给保存好以随时对照着我的文字讲解。
我们知道【rd_en】变为1是由于非阻塞赋值。那么它肯定是在某一个时钟上升沿到来后在非阻塞赋值的第2阶段变为1的。
那么我们先将初始条件设置为时钟周期处于【rd_en】变为1的之前的一个时钟周期。
【初始条件】假定某一个时钟上升沿到来时rd_en 0且本周期里面 rd_en 不会变为1。我们将这个时钟上升沿定义为0号上升沿。此时rd_en_d1与rd_en_d2的值均为0。
在0号时钟上升沿到来后的非阻塞赋值第1阶段计算非阻塞赋值的右侧表达式的值。这个时候表达式【rd_en_d1 rd_en】与表达式【rd_en_d2 rd_en_d1】的右侧表达式分别为【rd_en】与【rd_en_d1】它们都为0。
在0号时钟上升沿到来后的非阻塞赋值第2阶段将右侧表达式的值赋予左侧的变量。这样一来在这个阶段里rd_en_d1与rd_en_d2的值均被赋值为0与0号时钟上升沿到来时的值是一样的。
【1号时钟上升沿到来】此时rd_en为0且假定本上升沿到来后的非阻塞赋值第2阶段里rd_en被非阻塞赋值为1。此时rd_en_d1与rd_en_d2的值依然为0。
在1号上升沿到来后的非阻塞赋值第1阶段计算非阻塞赋值的右侧表达式的值。此时右侧表达式【rd_en】与【rd_en_d1】的值均为0。
在1号时钟上升沿到来后的非阻塞赋值第2阶段将右侧表达式的值赋予左侧的变量。这样一来在这个阶段里rd_en_d1与rd_en_d2的值均被赋值为0与1号时钟上升沿到来时的值是一样的。
【2号时钟上升沿到来】此时rd_en为1且本上升沿到来后的非阻塞赋值第2阶段里rd_en被非阻塞赋值为0。此时rd_en_d1 0rd_en_d2 0。
在2号上升沿到来后的非阻塞赋值第1阶段计算非阻塞赋值的右侧表达式的值。此时右侧表达式【rd_en】的值为1右测表达式【rd_en_d1】的值为0。
在2号上升沿到来后的非阻塞赋值第2阶段将右侧表达式的值赋予左侧的变量。这样一来rd_en_d1被赋值为1rd_en_d2被赋值为0。也就是rd_en_d1变为1而rd_en_d2不变。
【3号时钟上升沿到来】此时rd_en 0rd_en_d1 1, rd_en_d2 0。
在3号上升沿到来后的非阻塞赋值第1阶段计算非阻塞赋值的右侧表达式的值。此时右侧表达式【rd_en】的值为0【rd_en_d1】的值为1。
在3号上升沿到来后的非阻塞赋值第2阶段将右侧表达式的值赋予左侧的变量。这样一来rd_en_d1被赋值为0rd_en_d2被赋值为1。
【4号时钟上升沿到来】此时rd_en 0rd_en_d1 0, rd_en_d2 1。
在4号上升沿到来后的非阻塞赋值第1阶段计算非阻塞赋值的右侧表达式的值。此时右侧表达式
【rd_en】的值为0【rd_en_d1】的值为0。
在4号上升沿到来后的非阻塞赋值第2阶段将右侧表达式的值赋予左侧的变量。这样一来rd_en_d1被赋值为0rd_en_d2被赋值为0。
我们将上面的几个文字说明的信息摘录一下我们将【rd_en】【rd_en_d1】与【rd_en_d2】变为1的时机给摘录下来。
在1号时钟上升沿到来后在非阻塞赋值的第2阶段rd_en被非阻塞赋值为1。
在2号时钟上升沿到来后在非阻塞赋值的第2阶段rd_en_d1被非阻塞赋值为1。
在3号时钟上升沿到来后在非阻塞赋值的第2阶段rd_en_d2被非阻塞赋值为1。
所以呢rd_enrd_en_d1rd_en_d2它们分别是右边的信号比左边的信号延后一个时钟周期变为1。 四. 延时例题
本文第三节主要是为了向大家讲述延时逻辑。那个具体的文字表述不是重点重点时再次出现延时逻辑你得是能够明白。
下面我给大家来一个例题。 图5 如果第3节的知识大家看懂了那么图5中的代码其实是不难的。
图5中的代码依然是一个延时逻辑。
signalsignal_d1signal_d2signal_d3signal_d4signal_d5signal_d6这几个信号分别是右边的信号比左边的信号延后一个时钟周期。
延时逻辑大家明白了没 结束语
在本节我又水了一节。
延时逻辑也算是一个有趣的硬件代码逻辑。希望大家能学会。
本节里面我没有采用表格的方法来解读代码逻辑而是采用了文字说明的方法。其实两种方法只是不同的方法而已。你可以选择一种方法来研究你所关注的问题。
表格的话其实我还是比较推荐大家去使用它。图表应该算是现代社会里我们经常需要去观察和分析的材料吧。
会计里面有资产负债表炒股的人也需要去看股票价格的走势图。信息时代图表思维大概也是我们需要去训练的一种思维了。
本节结束。