搜索
bottom↓
回复: 372

跟着我从零开始入门FPGA(一周入门XXOO系列)

  [复制链接]

出0入0汤圆

发表于 2012-5-13 19:07:16 | 显示全部楼层 |阅读模式

这是一个大任务,但我打算只是引门外汉入门,大约7个帖子来完成,一周入门FPGA。

1、假设读者对硬件数字电路熟悉,比如自己可以用74芯片做跑马灯
2、C语言都比较熟悉,因为下面用的Verilog语言就跟它很类似,暂时规避晦涩的VHDL

我打算分几个部分
1、Verilog语法
2、组合逻辑设计
3、时序逻辑设计
4、阻塞和非阻塞
5、同步和异步设计
6、有限状态机
7、设计一个只有4条指令的CPU


如果你不需要自己设计,只需要看懂一些代码,理解Team中别人的意思。
这个帖子就是教你一周学会XXOO的

如果你已经入门而登堂入室了,这个帖子真的不应该看了,否则会退步的。


禁止转载,最讨厌那些用别人帖子,装衬一个克隆论坛的了。
没那人气的,就别折腾论坛,做论坛也要下本钱才行。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2012-5-13 19:07:47 | 显示全部楼层
本帖最后由 McuPlayer 于 2012-5-13 20:33 编辑

1、Verilog语法


没错,我们就是拿C语言照猫画虎,下面是一个“老虎”的模型。
我们一个个看他跟“猫”不一样的地方

module nand(
            input   in1,
            input   in2,
            output   out
);

    wire    tmp;
    assign tmp = in1 & in2;
    assign out = ~tmp;

endmodule


模块定义跟C语言的函数很相似吧
1、模块必须使用“module”关键字,他也没有返回值。
2、模块没有beginmodule,只有endmodule
3、模块对外接口有input,output,inout,但为了入门着想,只谈input和output

模块内部还有个中间变量耶,是不是看见了tmp就有很熟悉的感觉了。
没错,他就是中间“变量”,在硬件上他就是一根导线,wire望文生义即可。

看见了“=”就应该猜到这是赋值语句了,没错,但Verilog的语法要求前面必须有个苦B的assign关键字

至于“&”和“~”这2个运算符号,就不讲了吧,C语法搞不清的兄弟,对不住了


有人会说,你这“变量”到底是int还是long还是flot抑或double呢?
好了,咱继续照猫画虎,不过老虎毕竟跟猫是不一样的,比如老虎会虎啸,猫只会喵喵。

wire[7:0]   tmp;
这一下子把tmp从一根线,扩展成了8根线,觉得是7根线的自己去看C语言课本去。

好了,我们要虎啸了,同时喵喵几下,对比着看

wire[7:0]   tmp;
wire[3:0]   high;

assign high = tmp[7:4];     //虎啸的Verilog
high = tmp<<4;              //喵喵的C语言

硬件就是硬件,可以随意飞线,你甚至可以把tmp里面的bit6,bit3,bit1,bit7组成一个Nibble
不知道Nibble不要紧,它就是Half Byte的

assign high = {tmp[6],tmp[3],tmp[1],tmp[7]};        //虎啸的Verilog

high  = (tmp & 0x40) ? 0x08 : 0;                //喵喵的C语言
high |= (tmp & 0x08) ? 0x04 : 0;                //喵喵的C语言
high |= (tmp & 0x02) ? 0x02 : 0;;               //喵喵的C语言
high |= (tmp & 0x80) ? 0x01 : 0;;               //喵喵的C语言

这下知道喵喵跟虎啸的差距了吧,C语言,把如猫添翼?表达式都用上了,还是4行代码才表达出自己的意图。
当然,Verilog也有他的?表达式,那用上了,就真的是如虎添翼了

C语言的switch/case语句
switch(tmp)
{
    case 1:
        high =1;
        break;
    case 3:
        high =5;
        break;
    case 5:
        high =2;
        break;
    case 9:
        high =1;
        break;
    default:
        high =11;
}
Verilog的case语句
case(tmp)
    1:          high =1;
    2:          high =5;
    3:          high =1;
    4:          high =1;
    default:    high = 1;

发现了没,首先打字要少敲很多case了吧,case已经升级当主管了,小罗罗们直接跟这冒号就可以了。
细心的文艺青年,应该发现了一个大秘密,那个四处张扬,到处留种的break居然不见了。
Verilog不需要break了,它默认每个语句自动break,这时有人又担心,那我有2个语句咋办?

问得好,又有2个keyword要粉末登场了,begin/end
学会Pascal语言的朋友,肯定认得他俩,在C语言中被{和}所替代

Verilog本来也想用{和}的,毕竟写代码是要敲键盘的,能少敲谁也不愿意多敲。
可惜{和}被用掉了,用在了哪里?到上面找去,

case(tmp)
    1,2,3,4:
    begin
        high =1;
        high1 =3;
        high8 =9;
    end
    default:
        high = 1;

这个排版,是不是又点更像C语言的风格了
你也许已经看到了,C语言中多个case项公用一段代码的情况,在Verilog里面也有,而且更TMD的简洁

if/else语句就不讲了,这方面猫和老虎太像了,照猫画虎就**不离十了。


好了,下面有个用得非常多的always语句

always(tmp1, tmp2)
    begin
        out1 = tmp1 ^ tmp2;
        out2 = tmp1 + tmp2;
    end
又是喵喵和虎啸的区别了,C语言的while也是always的意思,但while不如always忠诚。
C的while语句,是随着CPU的时钟节奏,一步一步的走,然后Loop循环回来,直到永远或者有人叫她出台(霸王的break或者while条件不满足了)
Verilog的always可就忠诚多了,只要tmp1和tmp2中的任何一个变动,out1和out2都跟着动,clk来不来都会工作,这就是主动和被动的差别


好了,看到这里,你应该知道,文艺青年和苦B青年其实也有很多共同之处的,如果你认识文艺青年,那跟苦B青年交朋友也不难了。

出0入0汤圆

 楼主| 发表于 2012-5-13 19:09:44 | 显示全部楼层
2、组合逻辑设计

组合逻辑是神马?
所谓组合逻辑就是,一堆输入注定了一个(或多个)输出,明天你再送同样的这一堆输入,可以得到跟今天完全相同的结果。
或者说,输出的值跟先前任何状态没有一毛钱的关系,只跟当前的输入有关系。

来个最简单的:
assign out = in1 & in2;
这是个与门,out的值只跟in1和in2有关。

这时候?语句很有作用了,比如
assign out = sel ? in1 : in2;
这是一个二选一的选择器。

你肯定觉得二选一太简单了,来个4选一看看
assign out (sel==2'b00) ? in0 : (sel==2'b01) ? in1 : (sel==2'b10) ? in2 : (sel==2'b11) ? in3;
不知道你感觉如何,反正我从第二个问号开始花眼,咋办?
首先一个办法,?表达式的复合,我们可以用括号来区分层次,但仍然感觉很不直观。
想到了什么,C语言的switch/case,OK,我们就用Verilog的case语句写一下

always @(sel or in0 or in1 or in2)
    case(sel)
        2'b00:  out = in0;
        2'b01:  out = in0;
        2'b10:  out = in0;
        2'b11:  out = in0;
    endcase

OK,我们看看这个case语句是什么?没错,他就是那个真值表的美丽化身。
怎么,你还想到了卡诺图辅助逻辑表达式化简,当年读书时候,整天对着田字格横看竖看的,很神奇的。

现在我们有Verilog语言了,化简的事情交给综合器好了。
啥,你不知道综合器是啥?C语言的C编译器,你知道吧,他俩基本是一个地位的。

always的小老鼠后面的括号里不是有很多“变量”吗,那叫敏感信号。
只要敏感信号任何一个有变动,下面的语句就执行一次,其实这是个形象的说法,几乎是专门给C语言工程师定制的一个解释。

说到逻辑电路,我们找个非典型的用途吧-----地址译码
CPU就说是8051吧,其实其他的也一样

我们有个外设,内部有8个寄存器,我们打算把它安排到地址0xF080~0xF0087,设计它的片选信号

比较笨的方法:
assign sel = (addr==16'hF080) | (addr==16'hF081) | ...............
我就不敲完了,8个啊,复制完了,还要一个个修改,还要校对,够苦B的了

always @(addr)
    case(addr)
        16'hF080, 16'hF081, 16'hF082, 16'hF083, 16'hF084, 16'hF085, 16'hF086, 16'hF087:
            sel = 1;
        default:
            sel = 0;
    endcase
这个case语句简单多了吧,16'hF080的含义就是此数据有16个bit,h表示后面是十六进制表示的。
F080你要不知道什么意思,估计你们学校是体育老师讲计算机基础课,当然也可能是政治老师。

其实,case里面连续写8个项,然后一个冒号,感觉也很是苦B

那我们手工分析下0xF080~0xF0087的特征,高位的3个Nibble是F08,低位Nibble是0~7
我们再用二进制的方式看看:
1111 0000 1000 0000
1111 0000 1000 0001
1111 0000 1000 0010
1111 0000 1000 0011
1111 0000 1000 0100
1111 0000 1000 0101
1111 0000 1000 0110
1111 0000 1000 0111
---------------------------------------
1111 0000 1000 0xxx

这3个小x的含义我就不说了,这点归纳的逻辑都没有的话,您真不适合做工程师,适合做公务员。

always @(addr)
    casex(addr)
        16'b1111_0000_1000_0xxx:
            sel = 1;
        default:
            sel = 0;
    endcase
是不是帅呆了,如果你不是太粗心的话,应该看到了这个是casex而不是case


其实帅不是目的,泡到妞才是根本。看一个assign语句就可以搞定的事,何必罗嗦这么多呢。
assign sel = (addr==16'b1111_0000_1000_0xxx);

估计你还看到了一个小东西,那下划线。
没错,他就是个摆设,增加可读性的摆设,去掉也可以,不过我舍不得去掉。


C语言里如果要判断这个sel信号,一般用bit mask的方法
sel = ((addr&0xFFF8)==0xF0808);
看来照猫画虎,这招也可以用在这里,虽然代码稍微差异,思路近似。

关于case语句的一个注意事项,就是所谓的full-case,这个很重要
always @(addr)
    casex(addr)
        16'b1111_0000_1000_0xxx:
            sel = 1;
    endcase
那么,当地址不落在我们指定范围内的时候,没有语句来处理。
没来命令,就是要原地驻军。

其实相当于,
always @(addr)
    casex(addr)
        16'b1111_0000_1000_0xxx:
            sel = 1;
        default:
            sel = sel;
    endcase

天啊,sel=sel,这就是传说中的意外的latch,这跟我们的意图不一致
即使逻辑上可以完成指定功能,他也额外用掉了一个寄存器。

记住,用case语句的时候一定要full-case处理,除非你设计的就是寄存器

寄存器的latch是时序逻辑里面的内容
欲知后市如何,请听下回分解。

出0入0汤圆

发表于 2012-5-13 19:09:59 | 显示全部楼层
支持,跟着楼主哥学习

出0入0汤圆

发表于 2012-5-13 19:16:24 | 显示全部楼层
McuPlayer 发表于 2012-5-13 19:07
1、Verilog语法


module nand(
            input   in1,
            input   in2,
            input   out
);


哦 貌似 有点小错误 output out 吧

支持楼主原创

出0入4汤圆

发表于 2012-5-13 19:18:13 | 显示全部楼层
支持楼主,学习

出0入0汤圆

发表于 2012-5-13 19:20:16 | 显示全部楼层
LZ好人呀~  女士们~遇到LZ这样的好人就嫁了吧...

出0入0汤圆

发表于 2012-5-13 19:36:20 | 显示全部楼层
赶上直播了?前十有我,强力插入~

出0入0汤圆

发表于 2012-5-13 19:39:49 | 显示全部楼层
前排mark,楼主多多指教。坐板凳听课了

出0入0汤圆

发表于 2012-5-13 19:41:22 | 显示全部楼层
给入门者的好帖子

出0入0汤圆

发表于 2012-5-13 19:41:47 | 显示全部楼层
恩,很不错。

出0入0汤圆

发表于 2012-5-13 19:46:16 | 显示全部楼层
搬来板凳,坐下细看!

出0入0汤圆

发表于 2012-5-13 19:52:09 | 显示全部楼层
突发奇想------FPGA的汇编级别语言什么样子?

这个汇编应该对应RTL网表

出0入0汤圆

发表于 2012-5-13 19:59:38 | 显示全部楼层
tingke

出0入0汤圆

发表于 2012-5-13 20:14:26 | 显示全部楼层
支持楼主,继续

出0入0汤圆

发表于 2012-5-13 20:33:22 | 显示全部楼层
大凡高手如云,抢位听课。

出0入0汤圆

 楼主| 发表于 2012-5-13 20:35:26 | 显示全部楼层
zhanshenguilai 发表于 2012-5-13 19:16
module nand(
            input   in1,
            input   in2,
            input   out
);
哦 貌似 有点小错误 output out 吧
支持楼主原创


谢谢,已经改了
我都是一口气敲下来,就为了帮别人入门,所以就没有仿真

出0入0汤圆

发表于 2012-5-13 20:38:30 | 显示全部楼层
支持楼主!插入前十!

出0入0汤圆

发表于 2012-5-13 20:40:58 | 显示全部楼层
楼主,我只是专科毕业,没有软件基础能学会FPGA吗?现在搞FPGA开发的,一般招的都是研究生.我是不是学了也是白学,没人会理我的.

出0入0汤圆

 楼主| 发表于 2012-5-13 20:48:10 | 显示全部楼层
yhg-cad 发表于 2012-5-13 20:40
楼主,我只是专科毕业,没有软件基础能学会FPGA吗?现在搞FPGA开发的,一般招的都是研究生.我是不是学了也是白 ...

我也不好直接鼓励你什么,我说一个事实:
深圳有一家IC设计公司,曾经,设计工程师是清一色的中专生,设计8bit MCU的,兼容PIC的那种。
他们老板技术出身,所以能叫他的员工发挥最大的能力上限。

出0入0汤圆

发表于 2012-5-13 20:56:59 | 显示全部楼层
占个板凳,等后续

出0入0汤圆

发表于 2012-5-13 20:57:19 | 显示全部楼层
FPGA给我的印象:编译时间N长...这个认识正确吗?

出0入0汤圆

发表于 2012-5-13 20:58:10 | 显示全部楼层
太需要了,楼主辛苦了!

出0入0汤圆

发表于 2012-5-13 21:01:07 | 显示全部楼层
很好啊,需要楼主这样的人。楼主加油!坐等听课。。。。。。

出0入0汤圆

发表于 2012-5-13 21:27:00 | 显示全部楼层
nice!                             

出0入0汤圆

发表于 2012-5-13 21:30:39 | 显示全部楼层
支持楼主哥

出0入0汤圆

发表于 2012-5-13 21:33:29 | 显示全部楼层
XXOO开始了

出0入0汤圆

发表于 2012-5-13 21:41:01 | 显示全部楼层
mark                           

出0入0汤圆

发表于 2012-5-14 11:36:47 | 显示全部楼层
语言通俗易懂有趣,可以大大提高初学者的兴趣,不错,赞一个

出0入0汤圆

 楼主| 发表于 2012-5-14 18:22:41 | 显示全部楼层
本帖最后由 McuPlayer 于 2012-5-14 22:35 编辑

3、时序逻辑设计

所谓时序逻辑,简而言之,就是CLK驱动,不来时钟不干活,同时能自我保持。
最简单的例子,跑马灯

model led_led(input rst, input clk, output out0, output out1, output out2, output out3);
reg ary[3:0];

assign out0 = ary[0];
assign out1 = ary[1];
assign out2 = ary[2];
assign out3 = ary[3];
always @(clk)
begin
    if(rst)
        ary <= 4'h00;
    else
    begin
        ary[3] <= ary[2];
        ary[2] <= ary[1];
        ary[1] <= ary[0];
        ary[0] <= ary[3];
    end
end
endmodele

有人会说那个ary的“中间变量”是不是可以省掉,还真省不了,因为它不仅仅是“临时变量”。
它是个锁存器,寄存器-----------数据保持是它的特点。而wire信号是无法保持的。

当然那4个信号单独赋值,挺形象,但是不够紧凑,C语言可以用ary = ary<<1来表示,那Verilog就如下:
model led_led(input rst, input clk, output out[3:0]);
reg ary[3:0];
assign out = ary;
always @(clk)
begin
    if(rst)
        ary <= 4'h00;
    else
        ary <= {ary[2:0],ary[3]};
end

跑马灯,用组合逻辑做不出来,是因为它的输出不仅仅跟输入有关,也跟前一个状态有关。

看到时序逻辑,很多人发现了无比强大的clk信号,到处都有他的影子,他才是真正的到处留种的风流才子。

“输出不仅仅跟输入有关,也跟前一个状态有关”,这句话,应该很熟悉吧。 -----没错,就是状态机。
后面有个专门贴讲FSM,这是一个非常有效的解决问题的工具------智商99的人可以做到智商120的设计。
如果天才用了,那肯定要更加newbility了。

下面看个十进制的计数器,是前几天给一个初学者的sample,但愿这小哥真的去看懂了,而不是搞完毕设就完蛋鸟。

    module bcd_counter(rst, clk, qout);
    input rst;
    input clk;
    output[7:0] qout;

    reg [3:0] low;
    reg [3:0] high;

    assign qout ={high,low};

    always @(posdge clk)
        if(rst)
            begin
                low <= 4'h0;
                high <= 4'h0;
            end
        else
            begin
                case(low)
                0,1,2,3,4,5,6,7,8:
                    low <= low+4'h1;
                9:
                    begin
                        low <= 4'h0;
                        case(high)
                            0,1,2,3,4,5,6,7,8:
                                high <= high+4'h1;
                            9:
                                high <= 0;
                        endcase
                    end
                endcase
            end
    end module  

这里面有2个十进制数据,分别占用一个nibble---4个bit,其实就是BCD码。
使用了case语句来完成,而且两个case还套起来用了,跟C语言一个样,照猫画虎即可。

细心的文艺青年,应该发现了,module的定义貌似跟以前不一样了。
不用貌似,就是不一样了,这是2种风格,其实苦B的C语言也有这个风格的。
bool fun1(X,Y)
int X, Y;
{
}
C语言的古老风格,现在很少人用了,毕竟多敲键盘,不代表多干活。
那时候C语言还没有国际标准,此K&R C是以2个工程师的名字首字母命名的。
后来才有ANSI C和ISO C(C89/C90/C99),这巨人的肩膀好高啊,搞技术就不能有恐高症。

Verilog亦是如此,建议使用输入输出定义在括号里面的风格,至少要少码好几个字母不是。


不知道有没有人注意到,上面几个帖子用的都是always @(posdge clk),敏感信号列表中不见rst的身影。
下面的判断rst的信号,决定复位还是干活,这叫做同步复位。

同步复位,你要理解成rst一有效就复位就错了。同步的含义,与CLK同步,类似于与裆中央保持一致。

异步复位,是立即的。异步复位,同步释放。这个话题就比较远了,后面有个帖子,会专门说这个话题。


后面的会稍微有些难度,但我会为了入门的学习台阶,尽量把难的赶跑,容易的留下-----“男的赶跑,女的留下”。


预知后市如何,明天再看红盘绿盘。

出0入0汤圆

发表于 2012-5-14 20:17:13 | 显示全部楼层
坐下了,就不想起来了,楼主辛苦;

出0入0汤圆

发表于 2012-5-14 20:50:34 | 显示全部楼层
楼主有才。

出0入0汤圆

发表于 2012-5-14 20:58:42 | 显示全部楼层
顶楼主。。以前看过VERILOG。后来又忘记了。楼主强贴让我再次找到好好学习FPGA的感觉~

出0入0汤圆

发表于 2012-5-14 21:09:23 | 显示全部楼层
学习,形象、生动、风趣,楼主加油。 !!!

出0入9汤圆

发表于 2012-5-14 21:18:01 | 显示全部楼层
McuPlayer 发表于 2012-5-13 19:09
2、组合逻辑设计

组合逻辑是神马?
你肯定觉得二选一太简单了,来个4选一看看
assign out (sel==2'b00) ? in0 : (sel==2'b01) ? in1 : (sel==2'b10) ? in2 : (sel==2'b11) ? in3;
不知道你感觉如何,反正我从第二个问号开始花眼,咋办?
首先一个办法,?表达式的复合,我们可以用括号来区分层次,但仍然感觉很不直观。
想到了什么,C语言的switch/case,OK,我们就用Verilog的case语句写一下

always @(sel or in0 or in1 or in2)
    case(sel)
        2'b00:  out = in0;
        2'b01:  out = in0;
        2'b10:  out = in0;
        2'b11:  out = in0;
    endcase


请教一下,那个case四种情况输出的结果都是in0?不是说这个是四选 一吗?

出0入0汤圆

发表于 2012-5-14 21:19:02 | 显示全部楼层
下学期有EDA,先学学

出0入0汤圆

发表于 2012-5-14 21:39:34 | 显示全部楼层
养肥了一起看

出0入0汤圆

发表于 2012-5-14 21:52:59 来自手机 | 显示全部楼层
好强大   马克之
来自:amoBBS 阿莫电子论坛 Android客户端

出0入0汤圆

发表于 2012-5-14 22:15:53 | 显示全部楼层
学习啊

出0入0汤圆

发表于 2012-5-14 22:25:55 | 显示全部楼层
支持楼主 学习先

出0入0汤圆

发表于 2012-5-14 22:27:15 | 显示全部楼层
liangyurongde 发表于 2012-5-14 21:18
请教一下,那个case四种情况输出的结果都是in0?不是说这个是四选 一吗? ...

打错字了吧

出0入0汤圆

发表于 2012-5-14 22:30:15 | 显示全部楼层
McuPlayer 发表于 2012-5-14 18:22
3、时序逻辑设计

所谓时序逻辑,简而言之,就是CLK驱动,不来时钟不干活,同时能自我保持。

不知道有没有人注意到,上面几个帖子用的都是always @(posdage clk),敏感信号列表中不见rst的身影。
下面的判断rst的信号,决定复位还是干活,这叫做同步复位。

同步复位,你要理解成rst一有效就复位就错了。同步的含义,与CLK同步,类似于与裆中央保持一致。

异步复位,是立即的。异步复位,同步释放。这个话题就比较远了,后面有个帖子,会专门说这个话题。

期待楼主的下面的帖子

出0入0汤圆

 楼主| 发表于 2012-5-14 22:32:13 | 显示全部楼层
本帖最后由 McuPlayer 于 2012-5-14 22:36 编辑
shangdawei 发表于 2012-5-14 22:27
打错字了吧


谢谢你,确实是笔误。
我都是copy + paste + modify,这个漏掉了最后一项

另外,posedge这个keyword我经常多打一个a成了posedage
只是阿莫坛里无法做修改了,请看贴的兄弟包涵下。

出0入0汤圆

发表于 2012-5-14 23:39:18 | 显示全部楼层
这必须得支持啊

出0入0汤圆

发表于 2012-5-14 23:56:48 | 显示全部楼层
good

出0入0汤圆

发表于 2012-5-15 02:44:31 | 显示全部楼层
学习啊

出0入0汤圆

发表于 2012-5-15 07:44:38 | 显示全部楼层
继续吐丝吧

出0入0汤圆

发表于 2012-5-15 08:05:41 | 显示全部楼层
很好!占位听课

出0入0汤圆

发表于 2012-5-15 08:25:28 | 显示全部楼层
精辟~~~~~~~~~~~~~~~~~~~~~~~~~

出0入0汤圆

发表于 2012-5-15 08:32:12 | 显示全部楼层
学习,谢谢lz

出0入85汤圆

发表于 2012-5-15 08:32:53 | 显示全部楼层
跟帖学习

出0入0汤圆

发表于 2012-5-15 08:35:43 | 显示全部楼层
1ongquan 发表于 2012-5-13 19:52
突发奇想------FPGA的汇编级别语言什么样子?

这个汇编应该对应RTL网表

原语或者门级语言

出0入0汤圆

发表于 2012-5-15 08:48:12 | 显示全部楼层
感谢楼主,重新点燃FPGA,哈哈

出0入0汤圆

发表于 2012-5-15 09:14:58 | 显示全部楼层
啥时候能介绍个开发工具呀?这样写出来的代码是否有语法错误,还有仿真的结果就可以一目了然了。我之前没入门就是看了书没法实践

出0入0汤圆

发表于 2012-5-15 09:50:27 | 显示全部楼层
支持楼主,最近也在学FPGA

出0入0汤圆

发表于 2012-5-15 09:56:10 | 显示全部楼层
占位观看

出0入0汤圆

发表于 2012-5-15 10:10:33 | 显示全部楼层
谢谢楼主

出0入0汤圆

发表于 2012-5-15 10:28:53 | 显示全部楼层

出0入17汤圆

发表于 2012-5-15 13:03:33 | 显示全部楼层
支持原创

出0入0汤圆

发表于 2012-5-15 15:17:55 | 显示全部楼层
异步复位,同步释放, 是这样子吗?

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2012-5-15 18:11:44 | 显示全部楼层
本帖最后由 McuPlayer 于 2012-5-15 20:18 编辑

4、阻塞和非阻塞

话说大禹治水,因为他老爹治水失败被咔咔了,他不得已去顶缸。
他也琢磨啊,其父也不是等闲之辈,没搞定,说明必须得换个法子,否则自己也得被大哥给嗝屁了。
大禹父子治水,分别用的是阻塞和非阻塞的方法,下面我们就扯一下逻辑电路中的阻塞和非阻塞。

通常所说的阻塞和非阻塞,指的是always块中的语句。
always语句中有时序逻辑,也有组合逻辑。前者用非阻塞,后者用阻塞。
其实“阻塞”这个术语,也是专门给软件出身的电工看的,硬电工才懒得管你阻不阻的呢。

    reg[7:0] in1;
    reg[7:0] out;

    always @ (posedge clk)
    begin
        in1 <= in1+8'h01;
        out <= in1;
    end
endmodule


先从容易的下刀,我们先看看这个非阻塞的语句,它很简单,就是in1的自身完成一个自加一
注意这个“<=”,是不是又想起了C语言里用来搞指针的“->”,不过真的没有一毛钱的关系。

in1拿到的是clk上升沿之前的“in1”值再加1,跟clk上升沿之后的in1没有关系了。


正如,已毕业的小明的时候对还在读大四GF小芳承诺说,哥等你大学毕业就讨你做LP了。
时光如箭,日月如梭,时间如白驹过隙,学校7月份小芳走出了象牙塔的大学校门。
小明履行承诺,娶小芳为妻。话说,无巧不成书。
小芳大学毕业了,但大三的同学也该升级读大四了,正好里面也有个女娃的名字也叫小芳。
抢答开始,问:小明,娶的是哪个小芳?

答案是,去年读大四今年毕业的那个小芳,而不是去年大三今年大四的那个小芳。
您感觉拗口吗,反正我有点绕口令的感觉了。

非阻塞操作也是这个效果,你娶的是毕业(clk上升沿)之前的那个大四的小芳。

我们知道硬件是并行执行的,所以,上面的代码,这么写,效果一样。
        out <= in1;         //小明娶老婆
        in1 <= in1+8'h01;   //老小芳毕业,新小芳升级大四
   


但,如果把非阻塞改为阻塞的,那小明娶的老婆,到底是谁?且看分析。
        in1 <= in1+8'h01;   //老小芳毕业,新小芳升级大四
        out <= in1;         //小明娶老婆
所谓阻塞,就是一步一步来,就是写软件的那个思路,小明顺利娶他昔日的恋人为妻。

我们要调整语句顺序了,再看看小明的执行结果咋样
        in1 = in1+8'h01;    //老小芳毕业,新小芳升级大四
        out = in1;          //小明娶老婆

要顺序执行的哦,先完成“老小芳毕业,新小芳升级大四”,然后“小明娶老婆”。
小明娶到了刚刚大三升大四的小芳,你完全可以认定,小明是一个喜新厌旧的文艺青年。

而如果,做下语句的调整,就像下面这样
        out = in1;          //小明娶老婆
        in1 = in1+8'h01;    //老小芳毕业,新小芳升级大四
小明喜新厌旧的企图,被强大的阻塞语句,给堵回去了。

一般用阻塞语句来实现assign语句描述困难的组合逻辑,一般情况下代码块会比较小。
非阻塞的一般是用于时序逻辑,时序逻辑往往比较复杂,有时候复杂得有些变态。
如果月老执行Verilog语句的时候,一不小心,小明就娶错了老婆。


阻塞,有个地方用起来很方便,也许你也猜到了,testbench

tb代码本身,就不被用来综合到电路,所以,可以大胆使用阻塞语句
        #10 rst = 1;
        #10 clk = 0;
        #10 clk = 1;
        #10 clk = 0;
        #10 clk = 1;
        #10 rst = 0;
        repeat(100)
        begin
            #10 clk = 0;
            #10 clk = 1;
        end

这是一段,模拟单片机复位释放以及振荡器启动的激励。
反正是顺序执行的,就拿这写软件的脑袋来理解就够了,估计软电工都喜欢。


客户下单了,我得看看还有多少物料,还得准备安排焊接。

今天就先扯到这里吧。
请一定记住今天的学习任务,我们要帮小明娶到正确的老婆。

出0入0汤圆

 楼主| 发表于 2012-5-15 18:14:20 | 显示全部楼层
本帖最后由 McuPlayer 于 2012-5-15 18:15 编辑
shangdawei 发表于 2012-5-15 15:17
异步复位,同步释放, 是这样子吗?






这个电路,是典型的对异步Rest信号做同步化处理,其他的电路直接使用它同步后的rst信号即可,不用再理会什么同步异步之类的问题了。
相当于,一人做饭,多人吃饭。

出0入84汤圆

发表于 2012-5-15 18:29:32 | 显示全部楼层
果断收藏,跟着LZ有肉吃

出0入0汤圆

发表于 2012-5-15 18:58:22 | 显示全部楼层
记号,非常感谢

出0入0汤圆

发表于 2012-5-15 19:05:53 | 显示全部楼层
我觉得一周净搞Verilog都有点麻烦

出0入0汤圆

发表于 2012-5-15 19:44:34 | 显示全部楼层
支持一个,同时想问下楼主用的什么开发板,最近自己想画个FPGA的最小系统板,抽时间学学,还请楼主多多指教!

出0入0汤圆

发表于 2012-5-15 20:02:31 | 显示全部楼层
这个讲得很好,支持一下

出0入0汤圆

发表于 2012-5-15 21:10:57 | 显示全部楼层
支持楼主,搬板凳听课!

出0入0汤圆

发表于 2012-5-15 22:07:52 | 显示全部楼层
MARK

出0入0汤圆

发表于 2012-5-15 22:34:45 | 显示全部楼层
支持,学习了

出0入0汤圆

发表于 2012-5-16 15:01:16 | 显示全部楼层
楼主辛苦了!
占个坑位等下文。

出110入0汤圆

发表于 2012-5-16 15:12:06 | 显示全部楼层
McuPlayer 发表于 2012-5-15 18:11
4、阻塞和非阻塞

话说大禹治水,因为他老爹治水失败被咔咔了,他不得已去顶缸。

LZ神人也,够通俗,今天刚打算入门FPGA就遇到这么好的帖子

出0入0汤圆

 楼主| 发表于 2012-5-16 15:18:04 | 显示全部楼层
谢谢捧场

按照计划,今天还有一拙帖

出0入0汤圆

发表于 2012-5-16 15:32:30 | 显示全部楼层
讲得很出色, 有些我以前没注意到的地方 .....
关于阻塞我个人认为是语句顺序执行,而非阻塞则是语句执行顺序由综合器完成,也可以理解为不分先后并行执行,....
不知道对不对

等待LZ的FPGA做精密运算的例子.........

出0入0汤圆

发表于 2012-5-16 15:33:32 | 显示全部楼层
学习了

出0入0汤圆

发表于 2012-5-16 15:37:42 | 显示全部楼层
学习了,楼主辛苦

出0入0汤圆

 楼主| 发表于 2012-5-16 18:34:26 | 显示全部楼层
5、同步和异步设计

前面已有铺垫,同步就是与时钟同步。
同步就是走正步,一二一,该迈哪个脚就迈那个脚,跑的快的要等着跑的慢的。
异步就是搞赛跑,各显神通,尽最大力量去跑,谁跑得快,谁拿奖牌。

我们举个例子,SPI接口,他是一个低成本的单端的高速串行数据传输协议。
四个信号,nCS、SCK、MISO、MOSI

下面是一个Slave SPI的接口部分,简化了,

model mySPI(input nCS, input SCK, input MOSI, output MISO);
    reg[3:0]    bitcnt;
    reg[7:0]    shift_in;   //写入
    reg[7:0]    shift_out;  //读出

    reg[7:0]    data_wt;
    reg[7:0]    data_rd;

    always @(posdge SCK)
    if(nCS)
        bitcnt <= 0;
    else
    begin
        if(bit_cnt!=4'h7)
        begin
            bitcnt <= bitcnt+4'h1;
            shift_in <= {shift_in[6:0], MOSI};
            shift_out <= {shift_out[6:0], 0};
        end
        else
        begin
            bitcnt <= 4'h0;
            ...........
            data_wt <= deshift_in;
            shift_out <= data_rd;
        end
    end
endmodule

这段代码是同步的还是异步的?
其实,他远看是同步的,近看是异步的,仔细一看还是同步的。

大致一看,丫的还配时钟呢,按钟点走步,八成是同步的。
然后一想,不对啊,SPI的SCK是Master提供的,跟自家的全局时钟没有必然关系啊,异步的。
思索一阵,假如俺系统全局时钟都靠SCK不就是同步的了吗?

实际情况如何呢?
举个例子,SPI Flash,比如25系列,其实就是同步的,SCK就是全局时钟。

比如某ARM core的MCU内置SPI模块,为了简化问题,我们只谈Slave的情况,问题就来了。
ARM MCU肯定有其自家的时钟,SPI的Master又送来一个时钟,咋办呢?

当你发愁的时候,你该庆幸自己遇到了几乎所有入门的人都必须解决的问题----多时钟系统。

多时钟,各自都是同步,放在一起就是异步。
正如两队人马,都在走正步,共军走得快,国军走的更快,他们各自都是同步的,扯蛋到一块就是异步。
咋办呢?
丛林法则要起作用了,单一时钟同步化处理,势力小的听势力大的人安排。

model mySPI(input clk, input nCS, input SCK, input MOSI, output MISO);

    always @(clk)
    ...................................
endmodule

clk是自家的全局CLK信号,对方的SCK信号,只在自家CLK触发才看一眼对方的各个信号,包括SCK信号。
这就是强者的统战部,你家的可汗(SCK),见到我家皇帝(clk),也是称臣子。

当然,这个处理方法是有前提的,就是clk的频率要远远高于SCK信号。
所谓远远高于,就是即使我clk的上升沿,瞄你一眼,就不会漏掉你所有的表现。
根据XXXOOO定律,要达到采样不丢信息,尼玛的频率至少是人家的2倍,实际应用中一般保证4倍,或更高。
就好比有4个小弟的人,叫只有一个小弟的人,对自己称臣,听话大家就河蟹,不听就干你。

前面有朋友谈到了复位信号的同步化处理,最简单的就是复位和释放都同步处理,我前面几个帖子有用到。
复位,是什么,是杀头,复位释放是什么,是重新投胎。
你跟情敌斗志斗勇的时候,想到了制胜的一招时候,你觉得是立马去执行,还是等下一次例行见面时再执行。
当然是立马执行了,这不就是异步把情敌给复位了嘛。
你击败情敌之后,要对全班同学宣布的你胜利,是每天早会宣布呢,还是里面召集同学宣布呢?
此时大势已定,当然是按CLK四平八稳来得妥当,大家会认为你是一个做事不鲁莽,有步骤的,电工十佳青年。

所以,我们称之为,异步复位,同步释放。
always @ (posedge clk or negedge nRST)
    if (!nRST)
        击败情敌;
    else
        把击败情敌的战果宣布;
   

再举个例子,Memory的访问,为了简化,我们做个ROM,这样只有读的一种情况,适合理解记忆
model memory8(input[7:0] addr, output[7:0] dat)
    reg[7:0]    rom[255:0];
    assign dat = rom[addr];
endmodule

model memory8(input clk, input[7:0] addr, output[7:0] dat)
    reg[7:0]    rom[255:0];
    reg[7:0]    outbuf;

    assign dat = outbuf;
    always @(posedge clk)
        outbuf <= rom[addr];
endmodule

简单的是异步的,只要地址变化了,输出立马就表现。
我们实际使用的27系列的EPROM,61系列的异步SRAM,都是这样的,始终把OE信号置于有效即可。

复杂的就是同步的了,我不管你地址变了没,在CLK上升沿到来之前,我懒的理你。
异步的SRAM,刚查了下,也有61系列的; 看来不能以前缀来瞎子摸象了。

一般实际用的时候,异步SRAM肯定比同步的好用,同步的老要CLK,你是IO口模拟呢,还是怎么输出呢?
但同步的Memory也不是吃素的,吃的多必然长得壮,同步可以提高更高的传输速度。

该往回说了,为何同步电路可以提高更高的速度呢?

异步,就是赛跑,速度以跑得慢的人为准,团队精神嘛,这不能平均,只能搞木桶原理。
同步,就是大家按一个节奏,你慢的话,就用2个节奏完成,但必须按节奏。

这样负责协调的那个人,就是喊一二一的那个人(clk),可以把握全局的节奏来达到速度最大化。

所以一般FPGA里面都有全局时钟,强大的扇出能力,最小的传输延迟,因为他是老大,好资源他先挑的。
他就好比系统的原子铯钟,他很精确,我们每天跟他对一下时间,我们自家的表,就不会产生误差积累。

异步,2个队伍,各自有自家的老大,比如一个是地址线,一个是数据先,某个时刻,主控一抓。
可能地址线跑得快,数据线跑的慢,就会出现数据错位的情况,数字电路上叫竞争。
你作为运筹帷幄的总统,不能断定2个队伍能同事到达,你仍然用这个方法,你就是在冒险。

作为设计而言,应尽量避免竞争冒险。
如果系统简单,工期紧,速度要求低,逻辑简单,用异步的。
如果系统庞大,速度要求越高越好,逻辑交叉错节,坚决用同步的。
同步设计就是个工具,让智商90的人可以干智商120的人的工作。

Asynchronous 和 Synchronous 这两个单词我老是分不清
后来学软件学逻辑电路,给记住了,带A的要要冒尖的,是异步的

明天要讲的有限状态机,是以同步设计为基础的设计方式,然后我们就可以用90的智商做150智商的工作了。

出0入0汤圆

发表于 2012-5-16 19:24:09 | 显示全部楼层
MARK,有时间学习一下

出0入0汤圆

发表于 2012-5-16 19:28:46 | 显示全部楼层
资料很好,建议楼主出个PDF教程

出0入0汤圆

发表于 2012-5-16 19:49:43 | 显示全部楼层
膜拜下。

出0入0汤圆

 楼主| 发表于 2012-5-16 21:08:48 | 显示全部楼层
坐个翻页的沙发

出0入0汤圆

发表于 2012-5-17 14:27:50 | 显示全部楼层
McuPlayer 发表于 2012-5-16 18:34
5、同步和异步设计

前面已有铺垫,同步就是与时钟同步。

智商90变150,期待下一篇!

出0入0汤圆

发表于 2012-5-17 15:08:19 | 显示全部楼层
好文,带板凳跟。

出0入0汤圆

 楼主| 发表于 2012-5-19 21:55:42 | 显示全部楼层
6、有限状态机

状态机,只要C代码写过2年的人,估计无人不识君,稍微复杂的逻辑都可以借助状态机来简化问题。

为了方便,我们使用前面用过的一个例子,来说明状态机的应用,也就是说我们前面已经有意无意的用过状态机了。

我们以SPI的Slave接口,为例,来说明状态机的使用


为了简化问题
1、我们没有把信号同步到本地时钟
2、把其他信号同步到SCK
3、我们把SPI暂时按照单向来分析

下面,我们分析SPI通讯
1、nCS高电平时候,总线是空闲的
2、nCS低电平时传输数据
3、满了8个bit,凑够了一个字节,要保存当前已经收到的字节,并准备收下一个;

nCS高电平的时候,我们称之为idel态(IDEL)
接受0~7逐个bit的时候,称之为bit接受态(BIT_RECV)
收满一个字节,称之为字节转存态(BYTE_SAVE)

我们开始画状态转移图


model SlaveSPI(input nCS, input SCK, input MOSI, output MISO);

parameter IDEL = 0,
          BIT_RECV = 1,
          BIT_SAVE = 2;

    reg[3:0]    bitcnt;
    reg[7:0]    shift_in;   //写入
    reg[7:0]    shift_out;  //读出

    reg[7:0]    data;

    reg[1:0]    state;
    reg[1:0]    next_state;

    always @(*)
    begin
        case(state)
        IDEL:
            if(nCS==1'b1)
                next_state = IDEL;
            else
                next_state = BIT_RECV;
        BIT_RECV:
            if(nCS==1'b0)
            bgein
                if(bitcnt<4'h8)
                    next_state = BIT_RECV;
                else
                    next_state = BYTE_SAVE;
            end
            else
                next_state = IDEL;
        BYTE_SAVE:
            if(nCS==1'b0)
                next_state = BIT_RECV;
            else
                next_state = IDEL;
        defalut:
            next_state = IDEL;
        endcase
    end


    always @(posdge SCK)
        if(nCS)
            bitcnt=0;
        else
            state = next_state


    always @(posdge SCK)
        case(state)
        BIT_RECV:
            begin
                bitcnt <= bitcnt+4'h1;
                shift_in <= {shift_in[6:0], MOSI};
            end
        BYTE_SAVE:
            begin
                bitcnt <= 4'h0;
                data <= deshift_in;
            end
        endcase
   
我用了所谓的三段式,来描述这个状态机,用了3个always语句
第一个always用来描述状态转移的条件
第二个always用来描述状态转移
第三个always用来描述状态机的输出,也就是状态机实际要干的活


与前面帖子(同步和异步设计)中的SPI代码相比,是不是冗长了很多。
冗长,并不代表着脱裤子放屁,自找麻烦。您难道没有反显,代码很容易读懂了吗?

没错,这就是空间换时间的策略,我们写更长的代码来增强可分析性。

状态机的代码撰写一般不复杂,复杂的是状态机的构建过程,这个过程中,我们要分析
实际遇到的各个情况,同时把状态机进行优化,某些状态进行合并,某些状态去掉。
  
有人问,为何某些状态要去掉?
这要说下FSM的来头了,有限状态机,是有限的状态机。
自然界实际的状态机,往往起状态的数量,是非常大的,直接建模使用简直是劳民伤财。
而且,现实的往往是无限的状态机,这根本无法用于工程实现,所以有限状态机就横空出世了。

正如,软件算法中的DAG(Directed Acyclic Graph)有向无环图,比纯粹的图有实用价值。
二叉树,比多叉树,也更容易实现。

越说,软件和FPGA越近了。可谓是天下大势,分久必合,合久必分。

好了,这篇比较仓促,周六晚上专门来办公室写这个帖子。

本帖子中包含更多资源

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

x

出0入476汤圆

发表于 2012-5-19 22:49:01 | 显示全部楼层
正好可以学习。收藏

出0入0汤圆

发表于 2012-5-19 23:06:49 | 显示全部楼层
mARK很久没碰FPGA 了,回忆下

出0入0汤圆

发表于 2012-5-19 23:21:01 | 显示全部楼层
LZ 求友链啊~

出0入0汤圆

发表于 2012-5-23 00:00:28 | 显示全部楼层
继续啊...

出0入0汤圆

 楼主| 发表于 2012-5-23 09:38:03 | 显示全部楼层
最近比较忙,一个客户记着要货,一个客户软件出问题,同事处理不过来,我四处救火。
还有,这个连载贴的最后一贴了,我想写得稍微用心一点。

出0入0汤圆

发表于 2012-5-23 09:38:19 | 显示全部楼层
McuPlayer 发表于 2012-5-19 21:55
6、有限状态机

状态机,只要C代码写过2年的人,估计无人不识君,稍微复杂的逻辑都可以借助状态机来简化问 ...

请教LZ,你的状态转移图是用什么软件画的啊?

出0入0汤圆

发表于 2012-5-23 20:43:20 | 显示全部楼层
关注,继续

出0入0汤圆

发表于 2012-5-23 21:34:14 | 显示全部楼层
学习fpga.谢谢楼主

出0入0汤圆

 楼主| 发表于 2012-5-24 14:07:41 | 显示全部楼层
hy2515131 发表于 2012-5-23 09:38
请教LZ,你的状态转移图是用什么软件画的啊?

Windows的“画图”,台湾的工程师称之为小画家

出0入0汤圆

发表于 2012-5-24 14:41:08 | 显示全部楼层
入门来了。。

出0入0汤圆

发表于 2012-5-24 14:43:00 | 显示全部楼层
来晚了,没板凳,站着等下一课

出0入0汤圆

发表于 2012-5-24 15:22:58 | 显示全部楼层
开始学习FPGA

出0入0汤圆

 楼主| 发表于 2012-5-27 17:17:12 | 显示全部楼层
7、设计一个只有4条指令的CPU


我们要设计一个简单的CPU

既然做CPU,我们要做流水线的,要简单,做2级流水线就够了。

为了实例的简单,我们选择设计一个8bit的MCU的内核
仍然我们要简单,所以选择RISC的内核,类似PIC的结构
还是为了要简化,我们只支持4条指令
继续为了要简化,我们不考虑Status寄存器

有人会问,只有4条指令,你还加减法都有,有一个不就可以了。
这也是我有意的,你想,假设ALU只能做加法,你不觉得ALU这个名称太不名副其实了吗。

mov  A,#35H 把立即数mov到A寄存器
add  A,#42H (A) + 12 -> A
sub  A,#62H (A) - 12 -> A
JMP  imd    跳转到某地址


我们先给他们做机器编码,我们用16bit宽度的指令集编码

0x0035      00是MOV的OP code
0x0142      01是ADD的OP Code
0x0265      02是SUB的OP code
0x8000      80是JMP的OP CODE

我们继续看,指令集,用Verilog的方式来描述
16'b0000_0000_????_????     MOV
16'b0000_0001_????_????     ADD
16'b0000_0010_????_????     SUB
16'b1???_????_????_????     JMP

我们可以看到JMP的跳转地址范围是15个bit地址,也就是32K地址范围

有人说ALU很重要,好,我们就先来看ALU的组成,因为只有加减2种情况,所有ALU的OP代码只用1个bit表示
op为1的时候,做加法,为0的时候做减法。

module alu(input op, input[7:0] in1, input[7:0] in2, output[7:0] out)
    assign out = op ? (in1+in2) : (in1-in2);

看到上面的代码,估计不少人大跌眼镜,莫非传说中的alu就这么简陋。
没错,如果你只要做加法和减法,而且不考虑进位和溢出的ALU,就是这么easy的。

好了,cpu的运转过程,包括加载指令,解码指令,执行指令,大家都知道。

我们还要使用流水线技术,虽然这里不用也许更简单,但我们的目标是学习。

      一  |   加载指令1   |   加载指令2    |   加载指令3    |   ..........
----------+---------------+----------------+----------------+-----------------
      二  |               |   解码1 执行1  |   解码2 执行2  |   解码3 执行3

我们可以看到加载和解码和执行,并没有在一个周期中完成,而是分开了
在运行第二条指令的时候,CPU正在加载第三条指令,一心二用,事事不耽搁。

clkcnt;

always @(posdge clk)
    if(nCS)
        clkcnt <= 0;
        instr <= 0;
    else
        instr <= rom_dat_out;


下面是CPU的解码和执行过程

always @(posdge clk)
    if(!nCS)
    casex(instr)
        16'b0000_0000_????_????:        //MOV
            begin
                acc <= instr[7:0];
                pc <= pc + 16'h0001;
            end
        16'b0000_0001_????_????:        //ADD
            begin
                acc <= aluout;
                pc <= pc + 16'h0001;
            end
        16'b0000_0010_????_????:        //SUB
            begin
                acc <= aluout;
                pc <= pc + 16'h0001;
            end
        16'b1???_????_????_????:        //JMP
            begin
                pc <= instr[14:0];
                pc <= pc + 16'h0001;
            end


下面完成CPU核心和ALU之间的连线

assign aluop  = (instr[15:8]==8'h01);
assign aluin1 = acc;
assign aluin2 = instr[7:0];

alu alu1(aluop, aluin1, aluin2, aluout);

有人说,只看到执行指令,没看到解码指令的过程,有木有啊?当然有

16'b0000_0000_????_????     MOV
16'b0000_0001_????_????     ADD
16'b0000_0010_????_????     SUB
16'b1???_????_????_????     JMP

这几个逐个的case不就是在做解码?只是没有独立的解码步骤而已,因为太简单了嘛。

还有个地方,我故意做了遗漏,就是JMP指令的处理。

所谓流水线,就是取指和执行是同时的,但JMP的到来,带来了异常。
正常都是PC加一,所以取指其实一直在取下一条指令,而JMP的目标是不确定的,所以取的指令就不对了

我们一般称之为预测失败,然后继续取JMP目标地址的指令,但执行部分,会有一个空的指令周期。
从CPU的用户角度看,就是JMP指令要使用2个指令周期。

CPU的设计基本到此结束了。
关于FPGA,我也没有能力做太深入的讲解了,否则误人子弟,岂不是背离了我的目标。

我的blog基本上也是很少更新,你点进去看也没多少货。
有个哥们说得好,MP的博客,写得比别人的微薄还短小。

至此,这个帖子连载终于完成了,总算没有辜负自己和一些网友。

出0入0汤圆

发表于 2012-5-27 17:40:32 | 显示全部楼层
楼主加油  这个贴有意义

出0入0汤圆

发表于 2012-5-27 21:34:41 | 显示全部楼层
生动形象

出0入0汤圆

 楼主| 发表于 2012-5-27 21:49:38 | 显示全部楼层
谢谢捧场,整个7个帖子实际完成时间,是我预估的2倍

一是确实有些忙,二是人有天然的惰性
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 07:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表