HDL4SE:软件工程师学习Verilog语言(八)

8 用c语言写自定义基本单元

本节本来是要继续学习verilog语言的,但是软件开发进度条太沉重了,怎么推也推不动,只能慢慢磨了。没有软件的配合,学习效果就差了一些,因此把后面的内容提到前面来。当然也是因为沉迷于编程及游戏,资料都没有心思写了。
本节还是通过一个例子,来说明如何在HDL4SE中用c语言写自己的基本单元库,然后让verilog来调用。基本的想法是,用c语言写一个LCOM对象,实现基本单元所需要的IHDL4SEUnit, IHDL4SEDetector等接口,当然顺便实现IDList接口以便它能加入到双向链表中。用verilog描述它的模型,然后就可以包含在其他的verilog代码中通过实例化使用了。
这种基本单元可大可小,可以是一个小的运算单元,比如一个深度神经网络中用的基本乘累加算子,可以是一个比较大的单元,比如干脆就是一个RISC-V的核。我们这个例子是要实现一个俄罗斯方块游戏,基本单元就是游戏机的控制器。当然游戏机的显示器也可以看成是一个基本单元,作为设备挂在HDL4SE模拟器上,其实也是一个基本单元,只是没有用verilog代码直接调用罢了。此时verilog代码就很简单了,就是把控制器与模拟环境连接在一起,具体方式看后面的说明。
你可能会觉得有点投机取巧,用C语言来写个控制器,然后游戏就跑起来了,其中verilog代码几乎就没有了,仅仅是把游戏控制器和游戏面板连接起来。然而这正是做HDL4SE项目的初衷。HDL4SE可以支持用C语言来写数字电路基本单元模型,有几个理由:

  1. 在系统设计初期,很多模块都没有确定如何设计,此时就写verilog代码是不合适的,但是用c语言写一个原型系统,相对就轻松多了。因此才开始可以用c语言参与搭建系统,可以视为CModel。毕竟写c还是要比写verilog 的RTL描述要容易很多。
  2. 随着系统的概要设计迭代次数增加,逐步稳定,一部分模块可以用verilog来写了,此时将c语言模型和verilog编写的电路联合在一起模拟,可以检验verilog实现的正确性,而且能极大地加快仿真速度。有些部分甚至只是辅助开发的模块,其实最终都不需要写成RTL代码。
  3. 很多不适于用RTL编写的测试输入可以用c语言来写,这样可以简化系统复杂度,比如想做个深度神经网络识别的verilog代码,要从JPG文件中直接读图片数据,就可以用c语言写一个JPEG文件解码模块挂在系统中模拟,否则真用verilog RTL来写,好难啊,这里就不堪细说了,做过的都知道。即使写出来了,这个模块运行起来也快不起来,占用了很多仿真时间。一般FPGA开发或ASIC开发项目只好用软件将JPEG文件解码后转换成verilog能直接读的文本文件,然后用verilog代码来读,其实已经很不方便了。
  4. 可以在仿真过程中增加一些交互的内容,比如做GPU开发,可以马上看到绘图结果,做信号处理,直接看到信号处理结果(比如直接挂个FFT分析模块在系统中,并能动态显示频谱分布),做游戏,至少要能玩起来。这个比用纯的verilog RTL编玩后仿真,然后再去分析输出信号波形图或者输出文件,要爽很多。当然直接拉低了做数字电路那帮人的逼格。软件工程师从此包打天下,数字电路件开发而已。
  5. 可以将设备驱动程序软件和硬件一起模拟,让驱动程序软件在早期就介入系统设计,减少软硬设计之间的摩擦,这个就不多说了,做过类似项目的都知道其中的好处。
    我们还是从一个俄罗斯方块游戏例子开始,然后介绍其中的基本单元库的c语言实现,最后用verilog代码把它们在HDL4SE模拟器中连接起来,构成一个实际能玩的游戏。后面会随着学习深入,编译器软件的完善,逐步将c语言实现的部分替换成verilog实现,最终形成一个用verilog写的俄罗斯方块游戏。烧在FPGA里,可以做成一个游戏机呢,做成专用的ASIC芯片,可以用来造游戏机。

8.1 俄罗斯方块游戏

俄罗斯方块游戏看上去是这个样子的:

HDL4SE:软件工程师学习Verilog语言(八)

8.2.3 LCOM八股 – 转

这部分是八股文的核心,开题后,就要实现其中的各个功能,转的核心要点就是要按照开题的要求,逐个去实现每个接口的函数。这部分包括两个小部分,一个是实现LCOM对象的一些通用函数,一转:

static const char* terrisdeviceModuleInfo(){	return "1.0.0-20210610.0829 Terris Panel";}static int keypressed = 0;void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){	keypressed = 0;	if (action != GLFW_PRESS)		return;	if (key >= GLFW_KEY_RIGHT && key  GLFW_KEY_UP) {		key -= GLFW_KEY_RIGHT;		keypressed = (1  key);	}}static int terrisdeviceCreate(const PARAMITEM* pParams, int paramcount, HOBJECT* pObject){	sTerrisDevice* pobj;	int i;	pobj = (sTerrisDevice*)malloc(sizeof(sTerrisDevice));	if (pobj == NULL)		return -1;	*pObject = 0;	HDL4SEUNIT_VARINIT(pobj, CLSID_TERRISDEVICE);	INTERFACE_INIT(IHDL4SEUnit, pobj, terrisdevice, hdl4se_unit);	INTERFACE_INIT(IHDL4SEDetector, pobj, terrisdevice, hdl4se_detector);	DLIST_VARINIT(pobj, terrisdevice);	pobj->baseaddr = 0xF0000000;	pobj->name = NULL;	pobj->parent = NULL;	for (i = 0; i  paramcount; i++) {		if (pParams[i].name == PARAMID_HDL4SE_UNIT_NAME) {			if (pobj->name != NULL)				free(pobj->name);			pobj->name = strdup(pParams[i].pvalue);		}		else if (pParams[i].name == PARAMID_BASEADDR) {			pobj->baseaddr = pParams[i].i32value;		}	}	for (i = 0; i  9; i++) {		pobj->fromunit[i] = NULL;	}	memset(pobj->panelvalue, 0, sizeof(pobj->panelvalue));	pobj->panelvalue[12][7] = 4;	pobj->panelvalue[12][8] = 9;	pobj->panelvalue[12][9] = 3;	pobj->panelvalue[11][9] = 13;	if (!glfwInit())		return -1;	pobj->width = WIDTH;	pobj->height = HEIGHT;	pobj->wRead = 0;	pobj->count = 0;	pobj来源:饶先宏
                                                        

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年5月11日
下一篇 2021年5月11日

相关推荐