SpinalHDL之模拟信号和输入输出

本文作为SpinalHDL学习笔记第十五篇,记录使用SpinalHDL模拟信号相关API。

SpinalHDL学习笔记总纲链接如下:

SpinalHDL 学习笔记_spinalhdl blackbox-CSDN博客

可以使用 Analog/inout 功能定义三态信号。添加这些功能的原因有:

• 能够将三态信号添加到顶层(它避免了必须用一些手写的 VHDL/Verilog 包装它们)。

• 允许定义包含 inout 引脚的黑盒。

• 能够通过层次结构将黑盒的 inout 引脚连接到顶级 inout 引脚。

由于这些功能只是为了方便而添加的,因此请不要尝试使用三态逻辑的其他花哨的东西。如果你想对内存映射 GPIO 外设等组件进行建模,请使用 Spinal 标准库中的TriState/TriStateArray 线束,它抽象了三态驱动程序的本质。

目录:

1.模拟信号

2.输入/出

3.输入/出包装器

4.手动驱动模拟线束

1.模拟信号

Analog 是一个关键字,它允许将信号定义为模拟信号,在数字世界中可能意味着 0, 1, 或 Z (断开、高阻状态)。

例如:

case class SdramInterface(g : SdramLayout) extends Bundle {
val DQ = Analog(Bits(g.dataWidth bits)) // Bidirectional data bus
val DQM = Bits(g.bytePerWord bits)
val ADDR = Bits(g.chipAddressWidth bits)
val BA = Bits(g.bankWidth bits)
val CKE, CSn, CASn, RASn, WEn = Bool()
}

 

2.输入/出

inout 是允许你将 Analog 信号设置为双向(“in”和“out”)信号的关键字。

例如:

case class SdramInterface(g : SdramLayout) extends Bundle with IMasterSlave {
val DQ = Analog(Bits(g.dataWidth bits)) // Bidirectional data bus
val DQM = Bits(g.bytePerWord bits)
val ADDR = Bits(g.chipAddressWidth bits)
val BA = Bits(g.bankWidth bits)
val CKE, CSn, CASn, RASn, WEn = Bool()
override def asMaster() : Unit = {
out(ADDR, BA, CASn, CKE, CSn, DQM, RASn, WEn)
inout(DQ) // Set the Analog DQ as an inout signal of the component
}
}

3.输入/出包装器

InOutWrapper 是 一 个 工 具, 允 许 将 组 件 的 所 有 master TriState/TriStateArray/ReadableOpenDrain 线 束 转 换 为 inout(Analog(.. .)) 信 号。

它允许你保持硬件描述不受任何 Analog/inout 事物的影响,然后转换顶层以备综合。

例如:

case class Apb3Gpio(gpioWidth : Int) extends Component {
val io = new Bundle{
val gpio = master(TriStateArray(gpioWidth bits))
val apb = slave(Apb3(Apb3Gpio.getApb3Config()))
}
...
}
SpinalVhdl(InOutWrapper(Apb3Gpio(32)))

这将生成:

entity Apb3Gpio is
port(
io_gpio : inout std_logic_vector(31 downto 0); -- This io_gpio was originally␣
,→a TriStateArray Bundle
io_apb_PADDR : in unsigned(3 downto 0);
io_apb_PSEL : in std_logic_vector(0 downto 0);
io_apb_PENABLE : in std_logic;
io_apb_PREADY : out std_logic;
io_apb_PWRITE : in std_logic;
io_apb_PWDATA : in std_logic_vector(31 downto 0);
io_apb_PRDATA : out std_logic_vector(31 downto 0);
io_apb_PSLVERROR : out std_logic;
clk : in std_logic;
reset : in std_logic
);
end Apb3Gpio;

而不是:

entity Apb3Gpio is
port(
io_gpio_read : in std_logic_vector(31 downto 0);
io_gpio_write : out std_logic_vector(31 downto 0);
io_gpio_writeEnable : out std_logic_vector(31 downto 0);
io_apb_PADDR : in unsigned(3 downto 0);
io_apb_PSEL : in std_logic_vector(0 downto 0);
io_apb_PENABLE : in std_logic;
io_apb_PREADY : out std_logic;
io_apb_PWRITE : in std_logic;
io_apb_PWDATA : in std_logic_vector(31 downto 0);
io_apb_PRDATA : out std_logic_vector(31 downto 0);
io_apb_PSLVERROR : out std_logic;
clk : in std_logic;
reset : in std_logic
);
end Apb3Gpio;

4.手动驱动模拟线束

如果 Analog 线束没有被驱动,它将默认为高阻态。因此,要手动实现三态驱动程序(以防因某种原因无法使用 InOutWrapper 类型),必须有条件地驱动信号。

手动将 TriState 信号连接到 Analog 线束:

case class Example extends Component {
val io = new Bundle {
val tri = slave(TriState(Bits(16 bits)))
val analog = inout(Analog(Bits(16 bits)))
}
io.tri.read := io.analog
when(io.tri.writeEnable) { io.analog := io.tri.write }
}

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千穹凌帝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值