不好意思,又标题党了,为了骗阅读量没办法。。。
前言
今天为大家介绍一下python的MyHDL 库。MyHDL项目的目标是通过python语言的优雅和简洁性来增强硬件设计者的能力。
MyHDL是一种免费、开源的软件包,用于使用python作为硬件描述和验证语言。python是一种非常高级的语言,硬件设计者可以利用它的全部力量来建模和仿真他们的设计。此外,可以将设计转换为verilog或vhdl语言。这提供了一个融入传统设计流程的切入口。
这个库有完整的文档,网上还有翻译成中文的《MyHDL中文手册》,自行搜索。今天我为大家演示一个完整的使用MyDHL进行FPGA逻辑开发的流程。程序员都喜欢搞hello world, 我们硬件工程师都是弄个流水灯。
一、编写开发功能代码
流水灯的代码用硬件描述语言来写,可以写出花,今天我们就用最朴实的移位寄存器来实现。对0b00000001循环向左移位就可以实现流水灯的功能。由于我们使用的LED电路是低电平点亮,所以在输出的时候需要将输出按位取反。Python代码如下:
from myhdl import *
@block
def shifting_register(clock, reset,led_driver):
""" Incrementer with enable.
clock -- clock input
reset -- asynchronous reset input
reg -- output port to drive leds
"""
reg = Signal(modbv(1)[8:])
@always(clock.posedge, reset.negedge)
def shift():
if not reset:
reg.next = 1
else:
if reg[7] == 1:
reg.next = 1
else:
reg.next = reg<<1
led_driver.next = ~ reg
return shift
FPGA 开发板使用的12M晶振,所以我们还需要一个分频器,产生一个0.5Hz的时钟来驱动移位寄存器。代码也很简单:
from myhdl import *
@block
def clock_divider(clock, reset,clock_led):
""" Incrementer with enable.
clock -- clock input
reset -- asynchronous reset input
clock_led -- led clock output frequency is clock/6 000 000
"""
counter = Signal(modbv(0,min=0,max=2**24))
@always(clock.posedge, reset.negedge)
def divider():
if not reset:
counter.next = 0
clock_led.next = True
else:
counter.next = counter + 1
if counter == 3000000 :
counter.next = 0
clock_led.next = not clock_led
return divider
接下来我们在顶层连接两个模块,形成完整的设计。
from myhdl import *
from clock_divider import clock_divider
from shifting_register import shifting_register
@block
def running_led(clock, reset,led_driver):
""" Incrementer with enable.
clock -- clock input
reset -- asynchronous reset input
leds -- output for led driver
"""
clock_led = Signal(bool(0))
clock_divider_1 = clock_divider(clock, reset, clock_led)
shifting_register_1 = shifting_register(clock_led, reset, led_driver)
return clock_divider_1,shifting_register_1
二、仿真代码
逻辑开发的麻烦之处在于后期验证非常麻烦,不能像MCU那样进行断点仿真,所有前期的逻辑仿真非常重要。MyHDL同样支持对设计进行仿真,并且好像还可以联合Verilog进行仿真,不过这一个我没有尝试。
这里只放一个移位寄存器的textbench代码。完整的设计会上传到网盘,在文末能看到链接。
from myhdl import *
from running_led import running_led
@block
def running_led_testbech():
clock = Signal(bool(0))
reset = ResetSignal(0,active = 0, async= True)
led_driver = Signal(intbv(1)[8:])
runing_led_1 = running_led(clock,reset,led_driver)
HALF_PERIOD = delay(10)
@always(HALF_PERIOD)
def clockGen():
clock.next = not clock
@instance
def stimulus():
reset.next = 1
delay(20)
reset.next = 0
delay(20)
reset.next = 1
for i in range(100):
yield clock.negedge
raise StopSimulation()
@instance
def monitor():
print("clock led")
yield reset.posedge
while 1:
yield clock.posedge
yield delay(1)
print(" %s %s"%(int(clock),int(led_driver)))
return clockGen, stimulus,monitor,runing_led_1
tb = running_led_testbech()
tb.config_sim(trace=True)
tb.run_sim()
这段代码中添加了波形查看的支持,运行完测试脚本后会得到一个.vcd文件,这个文件可以用GTK打开来查看。
led_wave.JPG
三、转换为Verilog
在仿真验证设计完成之后,我们需要将python源代码转化为verilog,因为现行的各大FPGA供应商的工具还是只支持Verilog 和VHDL设计,当然现在也支持C和Matlab。但是HDL语言在严谨性和逻辑效率上还是有着无可比拟的有点的。
使用下面代码,可以将我们前面的设计文件转化为Verilog。
from myhdl import *
from running_led import running_led
clock = Signal(bool(0))
reset = ResetSignal(0, active=0, async=True)
led_driver = Signal(intbv(1)[8:])
runing_led_1 = running_led(clock, reset, led_driver)
runing_led_1.convert(hdl='Verilog')
转化完的结果如下:
// File: running_led.v
// Generated by MyHDL 0.10
// Date: Sun Jan 6 18:32:47 2019
`timescale 1ns/10ps
module running_led (
clock,
reset,
led_driver
);
// Incrementer with enable.
// clock -- clock input
// reset -- asynchronous reset input
// leds -- output for led driver
input clock;
input reset;
output [7:0] led_driver;
reg [7:0] led_driver;
reg clock_led;
reg [23:0] clock_divider0_counter;
reg [7:0] shifting_register0_reg;
always @(posedge clock, negedge reset) begin: RUNNING_LED_CLOCK_DIVIDER0_DIVIDER
if ((!reset)) begin
clock_divider0_counter <= 0;
clock_led <= 1'b1;
end
else begin
clock_divider0_counter <= (clock_divider0_counter + 1);
if ((clock_divider0_counter == 3000000)) begin
clock_divider0_counter <= 0;
clock_led <= (!clock_led);
end
end
end
always @(posedge clock_led, negedge reset) begin: RUNNING_LED_SHIFTING_REGISTER0_SHIFT
if ((!reset)) begin
shifting_register0_reg <= 1;
end
else begin
if ((shifting_register0_reg[7] == 1)) begin
shifting_register0_reg <= 1;
end
else begin
shifting_register0_reg <= (shifting_register0_reg << 1);
end
end
led_driver <= (~shifting_register0_reg);
end
endmodule
这个代码很简单,可以人工比对转化的正确性。
四、在FPGA上实现
得到Verilog文件,后面的设计流程就参照一般FPGA开发的流程了。
市场上用的最多的是Xilinx 和Altera的。但是前一段时间刚好一元夺宝中了一个Latticed的小开发板,叫小脚丫。就长这样!
step_mxo2_c1.png
今天就用它来开发了,第一次使用Lattice的芯片,就当给他们做广告了。
下面这是开发流程的详解。照着做就可以了,非常简单。
http://www.stepfpga.com/doc/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8Bstep-mxo2-c
管脚分配如下:
后记
其实是使用Python开发逻辑,没有看出足够大的优势,受限于并行电路描述的复杂性,语言上并没有体现出足够的简洁。但是能看到MyDHL在仿真上的优势,如果你在做图像算法,或者其他算法,可以直接调用电脑上的资源进行仿真。
工程链接:
链接:https://pan.baidu.com/s/1mQlNsM0jG7AbrWkn9SjfUg
提取码:xn7o
网友评论