MyHDL资料
时间:2009-08-23 来源:niexining
我并不是在盲目的翻译一些新的Python第3方模块. 事实上,我正在计划一个叫EmbeddedPython的项目, 目的是探寻用像Python这样的动态语言进行硬件开发的可能性。 要达到这个目标,需要一系列的工具: 语言,编译器,指令模拟器等等。 而现在就处在这样的搜集资料的阶段。 而我所关注的这些已有的项目,都是经过挑选的。 包括前段时间翻译的PyPy文档,和现在的这个,它们都是经得起考验的项目。 它们的创始人已经从各自角度努力了5-10年,甚至更长时间, 并且它们目前都发展良好,得到用户比较良好的反应。 当然,它们现在都还不算是明星。但是我们要看到它们的未来。 我相信开源的未来在于嵌入式,会有大批的人加入到Hardware Hacker的阵营。
原文网址: http://www.linuxjournal.com/article/7542
MyHDL: 一种基于Python的硬件描述语言
硬件设计进入21世纪。这个新工具把用可读性更好的语言和极限编程中 的测试原则带进硬件工程中。
数字化的硬件工程一般要使用一种特殊的语言,叫硬件描述语言(HDL). 之所以这样,是因为硬件设计自己独特的要求。主流的硬件描述语言是Verilog和VHDL.
现在,MyHDL要挑战传统思维,在硬件设计中使用通用的高级语言Python. 硬件设计者将会从这几方面受益:语言的设计良好,被广泛使用,开源。
基本概念 一种HDL会包含一些反应硬件本质的概念。 最突出的概念就是大规模并行模型。 HDL描述的是大量微小线程和它们之间的通信。 这样的话,必须有一种方法来得到尽可能轻量级的线程。 HDL描述在一个精心设置的运行时(runtime)环境中执行。 这个环境就是模拟器(simulator)。
在设计MyHDL时,我使用的是一种既符合Python精神, 又具有普遍性的最小化方法。MyHDL有个重要组成部分,叫用法模块; 还有一种结构,叫做myhdl,由Python包组成, 包含各种用来实现HDL中概念的objects。
下面这句Python代码把一些待会儿要用到的objects导进来:
from myhdl import Signal,Simulation, delay, now |
MyHDL用生成函数(generator functions)来实现并发. 生成函数与普通函数类似, 只不过它们返回值时不结束。 当一个生成函数被调用时,会返回一个生成器,一个很有意思的东西。 生成器有可恢复性,它保存各种调用之间的状态,把这些调用变成超轻量级线程。
下面是一个生成函数的例子,它能作为时钟产生器模型。
clk -- clock signal |
这个函数看起来像Python中的普通函数。 注意到函数代码开头的"while 1"循环,这是一种惯用方法, 用来让生成器一起出于活跃。 普通函数和生成函数间本质区别在于yield语句. yield有点像return,但是yield之后,生成器仍然处于活跃, 并且能从yield时的那个位置恢复。 而且,在这儿的yield还返回一个延时object. 在MyHDL里,这样的机制被用来向模拟器传递控制信号。 意思是,模拟器需要延时10个单位才能去恢复生成器。
参数clk代表一个时钟信号. 在MyHDL里,信号被用于生成器之间通信。信号的概念来自VHDL。 一个信号有两个值:只读的当前值,和通过.next属性修改的next值。 上面的例子中,时钟信号的next值总是与当前值相反。 时钟信号也就这样被触发。
为了模拟时钟生成器,我们先要创建一个时钟信号:
clk = Signal(bool(0)) |
这个始终信号用0作为初始值。然后,调用生成函数来创建时钟产生器:
clkgen_inst = clkgen(clk)
为了构成一个用处的小型演示,我们再创建一个生成器,
用来监视并打印时钟信号随时间的改变:
def monitor(): |
"yield clk"语句显示了一个生成器如果等待信号值的改变。
在MyHDL中,模拟器使用模拟器object的构造函数创建的, 这个构造函数拿任意多的生成函数作为参数。
sim = Simulator(clkGen_inst, monitor()) |
调用模拟器的run方法,让模拟器运行:
sim.run(50) |
这条语句让模拟器运行50个时间单位。输出如下:
$ python clkgen.py |
现在,我们来描述一个模拟器是如何工作的。
模拟算法受了VHDL的启发。VHDL的使用者比Verilog稍微少些,
但VHDL被当作仿效对象更合适。模拟器用时间驱动算法来调整所有生成器的运行。生成器yield出的object决定了该生成器需要等待何种事件而被再次激活。
在某个周期,一些生成器被激活,当且仅当该周期它们等待的事件发生。
在第一个周期,所有生成器都是活跃的,信号的next值根据当前值确定下来。
第二个周期时,当前值就是上一个周期的next值。
随着信号值的变化,被激活的生成器也相应改变。就这样,模拟周期不断重复。