参考
Vitis HLS 例子
myhdl文档
Verilog规则和常用模板
安装 Python 依赖
bash
复制代码
pip install myhdl
流水灯
led_shift.py
python
复制代码
from myhdl import block, always_seq, Signal, ResetSignal, intbv, instance, delay, Simulation, StopSimulation, now, traceSignals
# -----------------------------
# LED 循环左移模块
# -----------------------------
@block
def led_shift(clk, reset, led):
"""
功能:
实现一个循环左移 LED 的逻辑
输入:
clk : 时钟信号
reset : 异步复位信号,高有效
led : LED 状态寄存器,intbv类型
行为:
每个时钟上升沿,将 LED 当前值循环左移一位
"""
# 获取 LED 信号的位宽
width = len(led)
# -----------------------------
# 顺序逻辑
# -----------------------------
@always_seq(clk.posedge, reset=reset)
def logic():
# LED 循环左移操作:
# 1. led << 1 : 左移一位
# 2. led[width-1] : 原最高位作为最低位补回,实现循环
# 3. [width:] : 保证截断到原位宽
led.next = intbv((led << 1) | led[width-1])[width:]
return logic
# -----------------------------
# 测试平台
# -----------------------------
@block
def testbench():
# -------------------------
# 信号定义
# -------------------------
# 时钟信号
# 类型: bool
# 初始值: 0
clk = Signal(bool(0))
# 异步复位信号
# 类型: ResetSignal
# 初始值: 1(复位状态)
# active=1 表示高电平有效复位
# isasync=True 表示异步复位(不依赖时钟)
reset = ResetSignal(1, active=1, isasync=True)
# LED 状态信号
# 类型: intbv
# 初始值: 0b00000001(最低位亮,其余熄灭)
# 位宽: 8 位
led = Signal(intbv(0b00000001)[8:])
# 实例化 LED 循环左移模块
led_inst = led_shift(clk, reset, led)
# -------------------------
# 时钟生成器
# -------------------------
@instance
def clkgen():
"""
产生周期为 20 单位时间的方波时钟信号
"""
while True:
clk.next = not clk
yield delay(10) # 每 10 个时间单位翻转一次,得到 20 单位周期
# -------------------------
# 仿真激励
# -------------------------
@instance
def stimulus():
# 初始复位
reset.next = 1
yield delay(20) # 保持复位 20 时间单位
reset.next = 0 # 解除复位
# 打印 LED 循环左移的状态
for i in range(16):
print(f"t={now()} LED: {int(led):08b}")
yield delay(20) # 每隔一个时钟周期打印一次
# 仿真结束
raise StopSimulation
return led_inst, clkgen, stimulus
# -----------------------------
# 主程序入口
# -----------------------------
if __name__ == "__main__":
# -----------------------------
# 仿真(生成 VCD 波形)
# -----------------------------
# 调用 testbench() 返回实例再传给 traceSignals
tb = traceSignals(testbench())
# 创建仿真对象
sim = Simulation(tb)
# 运行仿真
sim.run()
# -----------------------------
# Verilog 转换
# -----------------------------
# -----------------------------
# 时钟信号定义
# -----------------------------
# 类型: bool
# 初始值: 0
clk = Signal(bool(0))
# -----------------------------
# 异步复位信号定义
# -----------------------------
# 类型: ResetSignal
# 初始值: 1(复位状态)
# active=0 表示低电平有效复位,可根据硬件需要修改
# isasync=True 表示异步复位
reset = ResetSignal(1, active=0, isasync=True)
# -----------------------------
# LED 信号定义
# -----------------------------
# 类型: intbv
# 初始值: 0b00000001
# 位宽: 8 位
led = Signal(intbv(0b00000001)[8:])
# 实例化 DUT
dut = led_shift(clk, reset, led)
# 转换成 Verilog 文件
dut.convert(hdl='Verilog')
执行结果
bash
复制代码
PS D:> python .\led_shift.py
t=20 LED: 00000001
t=40 LED: 00000010
t=60 LED: 00000100
t=80 LED: 00001000
t=100 LED: 00010000
t=120 LED: 00100000
t=140 LED: 01000000
t=160 LED: 10000000
t=180 LED: 00000001
t=200 LED: 00000010
t=220 LED: 00000100
t=240 LED: 00001000
t=260 LED: 00010000
t=280 LED: 00100000
t=300 LED: 01000000
t=320 LED: 10000000
生成的verilog
led_shift.v
bash
复制代码
// File: led_shift.v
// Generated by MyHDL 0.11.51
// Date: Mon Jan 5 08:29:06 2026 UTC
`timescale 1ns/10ps
module led_shift (
clk,
reset,
led
);
input clk;
input reset;
output [7:0] led;
reg [7:0] led;
always @(posedge clk, posedge reset) begin: logic
if (reset == 1) begin
led <= 1;
end
else begin
led <= ((led << 1) | led[(8 - 1)])[8-1:0];
end
end
endmodule
点击,灯翻转
python
复制代码
from myhdl import block, always_seq, Signal, ResetSignal, intbv
# -----------------------------
# my_led_key 模块
# -----------------------------
@block
def my_led_key(clk, reset, key, led):
"""
功能:
按键控制 LED 取反,带消抖功能
输入:
clk : 时钟信号
reset : 异步复位信号,高有效
key : 按键输入(未消抖)
输出:
led : LED 输出
参数:
消抖通过计数实现,按键稳定 N 个时钟周期后才认定按下
"""
# -----------------------------
# 消抖相关参数
# -----------------------------
DEBOUNCE_WIDTH = 16 # 消抖计数位宽(可调)
MAX_COUNT = 2**DEBOUNCE_WIDTH - 1 # 消抖计数最大值
# -----------------------------
# 消抖寄存器定义
# -----------------------------
key_sync_0 = Signal(bool(0)) # 按键同步寄存器 0
key_sync_1 = Signal(bool(0)) # 按键同步寄存器 1
key_cnt = Signal(intbv(0, min=0, max=MAX_COUNT+1)) # 消抖计数器
key_state = Signal(bool(0)) # 消抖后的按键状态
# -----------------------------
# 按键同步 & 消抖逻辑
# -----------------------------
@always_seq(clk.posedge, reset=reset)
def debounce():
# 两级寄存器同步按键信号,消除亚稳态
key_sync_0.next = key
key_sync_1.next = key_sync_0
# 如果按键与消抖状态一致,则计数清零
if key_sync_1 == key_state:
key_cnt.next = 0
else:
# 按键状态变化,计数累加
if key_cnt < MAX_COUNT:
key_cnt.next = key_cnt + 1
else:
# 当计数达到最大值,认为按键状态稳定
key_state.next = key_sync_1
# LED 取反
led.next = not led
return debounce
# -----------------------------
# 主程序:生成 Verilog
# -----------------------------
if __name__ == "__main__":
# -----------------------------
# 信号定义
# -----------------------------
clk = Signal(bool(0)) # 时钟
reset = ResetSignal(1, active=0, isasync=True) # 异步复位,高有效
key = Signal(bool(1)) # 按键输入
led = Signal(bool(1)) # LED 输出
# -----------------------------
# 实例化 DUT
# -----------------------------
dut = my_led_key(clk, reset, key, led)
# -----------------------------
# 转换为 Verilog
# -----------------------------
dut.convert(hdl='Verilog', name='my_led_key')
不规则方波
python
复制代码
from myhdl import block, always_seq, Signal, ResetSignal, intbv
@block
def my_led_key(ap_clk, ap_rst, key, led, sys_clk_freq=50_000_000):
"""
PWM循环输出 + 按键取反LED(低有效)
"""
# 高低时间计数
H1 = int(sys_clk_freq * 1e-3) # 1ms
L1 = int(sys_clk_freq * 2e-3) # 2ms
H2 = int(sys_clk_freq * 3e-3) # 3ms
L2 = int(sys_clk_freq * 4e-3) # 4ms
H3 = int(sys_clk_freq * 6e-3) # 6ms
L3 = int(sys_clk_freq * 6e-3) # 6ms
TOTAL = H1 + L1 + H2 + L2 + H3 + L3
# 信号定义
cnt = Signal(intbv(0, min=0, max=TOTAL))
pwm_val = Signal(bool(0)) # 仅由PWM always_seq驱动
led_reg = Signal(bool(0)) # 最终LED输出寄存器
# 按键同步消抖
key_sync0 = Signal(bool(1))
key_sync1 = Signal(bool(1))
key_last = Signal(bool(1))
# -----------------------------
# PWM计数器逻辑
# -----------------------------
@always_seq(ap_clk.posedge, reset=ap_rst)
def pwm_logic():
if cnt < TOTAL - 1:
cnt.next = cnt + 1
else:
cnt.next = 0
if cnt < H1:
pwm_val.next = 1
elif cnt < H1 + L1:
pwm_val.next = 0
elif cnt < H1 + L1 + H2:
pwm_val.next = 1
elif cnt < H1 + L1 + H2 + L2:
pwm_val.next = 0
elif cnt < H1 + L1 + H2 + L2 + H3:
pwm_val.next = 1
else:
pwm_val.next = 0
# -----------------------------
# 按键逻辑,只控制LED输出,不改pwm_val
# -----------------------------
@always_seq(ap_clk.posedge, reset=ap_rst)
def key_logic():
# 按键同步
key_sync0.next = key
key_sync1.next = key_sync0
# 检测下降沿按键(低有效)
if key_last and not key_sync1:
led_reg.next = not led_reg # LED取反
key_last.next = key_sync1
# 输出LED = PWM或按键控制取反
led.next = pwm_val ^ led_reg
return pwm_logic, key_logic
# -----------------------------
# 生成Verilog
# -----------------------------
if __name__ == "__main__":
from myhdl import Signal, ResetSignal
ap_clk = Signal(bool(0))
ap_rst = ResetSignal(1, active=1, isasync=True)
key = Signal(bool(1))
led = Signal(bool(0))
SYS_CLK_FREQ = 50_000_000
dut = my_led_key(ap_clk, ap_rst, key, led, SYS_CLK_FREQ)
dut.convert(hdl='Verilog')