本文作为SpinalHDL学习笔记第十五篇,记录使用SpinalHDL模拟信号相关API。
SpinalHDL学习笔记总纲链接如下:
可以使用 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 }
}
标签:std,val,SpinalHDL,输入输出,模拟信号,downto,io,logic,apb
From: https://blog.csdn.net/m0_59092412/article/details/140397929