【精品博文】吴明系列博文:FPGA 需要怎样的编程语言来做HLS?
《FPGA 何去何从》中我提到FPGA 更高级别的设计方式,姑且就叫HLSL(High Level Synthesis Language)吧,区别与Xilinx的 HLS。本文我就聊聊什么样的编程语言更合适用来做HLS,C,Python,Ruby,Go,SystemVerilog......,又或者都不是,又或者我们是不是应该创造一种全新的语法?(目前自是我一点点的想法而已,而且我的想法变化很快,想想半年前我才真正接触sv :)
在摸索语法之前,我们来看看FPGA设计里面是怎样的世界,FPGA里面数据是怎么处理的?更基本的,FPGA里面的数据又是什么样的形式呢?“register,wire,logic,parameter,signal,variable”,嗯,这些都是对的,这是最基本的数据表现形式,从语法上和其他语言的没有太大区别。既然太大区别,这些编程语言的数据都是保存在内存或者寄存器上,用另外一种编程语言完成当前编程语言的活,也是可以的,毕竟都是图灵完备。然而,真的只是这样而已吗?
在我看来,CPU的数据保存在内存中,也就是空间中,但是FPGA的数据保存在时间中,CPU获取数据的地址,下面连着的一片内存就是保持数据的,FPGA确实相同的寄存器,从第X个时钟到第X+n个时钟内,流过寄存器的data 也可以当成数据格式,也就是AXI AVALON 这些总线的表现形式,状态机也算是一种“时间数据格式”。我称这种数据方式为流(stream)或过程,cpu也有stream的形式,比如向一个文件写入数据。只是cpu stream更多的是作为数据搬运,而不是处理,处理是在内存的时候就已经做了。FPGA不一样,它没有足够的寄存器来先保存数据做处理(FPGA嵌入核控制也是CPU形式),只能是在stream存在的时间片内进行处理,所有的stream都是real time。现实世界很多都是stream的形式,网络传输,视频,音频,或许以后的计算是FPGA这种stream式的分布计算,:),so
拿面向空间的编程语言去设计面向时间的数据当然处处是坑。
既然是流的数据,那么语法要怎么定义呢?让我们想想stream需要哪些操作,以axi stream来示例吧
stream 操作方法
1、流生成:控制流生成,stream.begin()
2、流拼接:stream0+stream1+stream2
3、流中数据检索:第一个数据stream[0],向量数据stream[0:9],stream[4:],stream[:-1]
再规定一些语法约束:
1、stream,只能从单个master到单个slaver
因为是stream设计,本身会提供一些带stream interface的模块(sv,verilog,vhdl,提供设计)
1、流生成模块
2、IP输入输出是stream interface
3、流数据抓取模块,抓取特定index的数据
那么来看看真实设计又会变成什么样呢,举个简单的设计:把从mac流中提取udp 源 port,和 udp 目的port通过串口发送出去,udp数据通过从新封装IP后发送到网络上。(已有资源,stream基本模块,UART IP,Ethernet IP)
代码:
IP.rx_stream = mac.rx_stream[6+6+2:] //获取 ip 帧
udp.rx_stream = IP.rx_stream[20:] //获取 udp 帧
uart.tx_stream[0:7] = {udp.rx_stream[4:7],udp_rx_stream[0:3]} //拼接成UART stream
uart.tx_stream.begin( udp.rx_stream.last) //udp stream last 会触发uart stream 发送
new_ip.head_stream[0:19] = ...... // 填入新的 数据
new_ip.tx_stream = new_ip.head_stream + udp.rx_stream[8:] //生成新的ip
new_mac.tx_stream = {mac 头} + new_ip.tx_stream + {mac fcs} // 生成要发送的mac帧
所有功能就已经写完了,而且告诉大家,上面的代码,我已经可以实现 全部自动解析成systemverilog