现代专用集成电路的设计是借助于电子电路设计自动化(EDA)工具完成的。学习和掌握硬件描述语言(HDL)是使用电子电路设计自动化(EDA)工具的基础。

    学过单片机的都知道,我们的程序代码是一条指令一条指令来执行的。CPU 首先通过总线,读取一条指令,然后解析这条指令,再然后执行这条指令。我们写的 C 代码总是一条一条地执行。如果我们同时要处理 10 个子程序,那么 CPU 必须一个个子程序来执行。如果有些实时性较高的,如扫描下矩阵键盘,VGA 刷个屏,都需要中断来实现。如果刷屏时间比较长,就会影响到你按键的灵敏度。另外比如,我们的单片机在用串口接收数据,并且也要发送数据,同时我们的单片机要处理外部的 IO 信号,如果我们的 IO 信号非常快,并且有几百个信号,可能同一个时刻触发,很显然,如果这些信号比较快,那么我们的单片机,就没法实现了。   

    这是笔者简单举了两种情况,那么如果使用 FPGA 就可以很方便地解决以上问题。由于 FPGA 的并行性,不管是扫描键盘,还是扫描 VGA,都可以把它们做成独立的模块,时间上没有冲突,每个模块可以同时执行。

    再比如用一个 FPGA,就可以同时完成串口的收发,以及 IO 的监控,因为 FPGA的程序实际上就是电路,是瞬间就完成了,我们只要用 Verilog 写出来相应功能的程序模块,这些模块是同时运行的。

    这样看来 FPGA 真是太强大了,太完美了。但不要高兴地太早,由于 FPGA 可以在一个时钟内,完成多条语句的赋值,但是如果赋值必须有个前后顺序呢?也就是需要一步步的完成,怎么办?如果说并行控制是 FPGA 的优点,那么顺序控制就是他的不足之处。世界上永远没有完美的东西,我们在获得一种优势的时候,往往也获得了一种劣势。但是,办法总比问题多。

a、顺序控制的第一种办法——状态机设计

    可以说,我们用 Verilog 来写程序,状态机无处不在。顾名思义,通过设计状态机,我们可可以控制 Verilog 让他该快的时候快,该慢的时候慢,该做什么的时候就做什么。这才是我们想要的。状态机是很不错的东西,初学者对他望而生畏,而熟悉 Verilog 语言的人都对其会爱不释手。n

b、顺序控制的第二种方法——FPGA 中运行 CPU

    FPGA 也可以运行 CPU?是的,没错,FPGA 也可以像单片机一样使用,这样我们就可以用 C 代码来一条条指令来执行了,这不是太强大了?是的,没错。关键的问题是,我们是可以把一些逻辑控制顺序复杂的事情用 C 代码来实现,而实时处理的部分仍然用 Verilog 来实现。并且那部分 Verilog 可以被 C 代码控制。Xilinx FPGA 目前支持的CPU 有 Microblaze,ARM9,POWERPC,Cortex A9(zynq 是 Xilinx 比较新的一款片子,完美的将 Cortex A9 和 FPGA 整合到一起,有兴趣的可以淘宝搜索 Mi Z702、zedboard)其中Microblaze 是一款软 CPU,是软核。ARM9,Cortex A9 和 POWERPC 是硬核。

这里有两个概念,软Core和硬Core:

    1)软核就是用代码就是能现的 CPU 核,这种核配置灵活,成本较低。可以在任何资源足够的FPGA中实现,使用非常灵活。而且在大容量的FPGA中还可以集成多个软core,实现多核并行处理。但是要占用FPGA 宝贵的资源。

    2)硬核就是一块电路,做到 FPGA 内部,方便使用,性能更高。比如 Xilinx 的 DDR内存控制器,就是一种硬核,其运行速度非常高,我们只要做些配置,就可以方便使用,缺点是不够灵活。

  两种核可谓各有所长。

不过,FPGA还是有缺点。对于某些高主频的应用,FPGA就无能为力了。现在虽然理论上FPGA可以支持的500MHz,但在实际设计中,往往200MHz以上工作频率就很难实现了。

FPGA还是ASIC ?

    根据具体看情况而定,从我们上面的一些介绍,笔者相信你已经有一定的判断能力了。笔者的建议是,低速场合,实时性要求的低的地方用ASIC,有些功能用ASIC 方便的用ASIC,成本低的用ASIC。排除那些可以不用FPGA 地方,那么剩余的就要考虑是不是用FPGA 来实现更加方便。一般来说,FPGA 程序开发相对来说要难度大一些,并且成本要高一些。

    讲了这么多的背景知识,我们来看一小段代码:

C代码:




  • u32sum(a,b)




  • {




  •   a=a+1;




  •   b=b+1;




  •   c=a+b;




  •   return c;




  • }


Verilog语言:




  • always@(posedgeclk)




  •   begin




  •     a = a + 1;




  •     b = b + 1;




  •     c = a + b;




  •   end


    同样是实现了求和,但是,C 代码需要 N 多个(很多)CPU 周期才得出结果,而用Verilog 一个 clk 周期就计算出来了。