myhdl

参考

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')
相关推荐
1560820721913 小时前
上位机通过UDP接口与FPGA互联的重传机制
fpga开发
1560820721913 小时前
UDP传输数据丢包原因分析
fpga开发
Aaron158815 小时前
基于RFSOC+VU13P在5G波束成形中的技术应用分析报告
人工智能·算法·5g·fpga开发·硬件架构·信息与通信·基带工程
石头明月15 小时前
基于XC7A35T的DDR3 IP核使用
嵌入式硬件·fpga开发
1560820721915 小时前
基于FPGA实现的UDP应用调试记录
fpga开发
Fpga_User15 小时前
FPGA的版本管理
fpga开发
点灯大师李1 天前
Zynq FPGA UART程序固化完整流程文档
fpga开发
坤驰科技1 天前
测风激光雷达数据采集解决方案
fpga开发
博览鸿蒙1 天前
FPGA 可以转 IC 设计吗?需要具备哪些条件
fpga开发
GateWorld1 天前
真双端口RAM在FPGA中使用
fpga开发·ram·实战经验·tdp-ram使用