本文作为SpinalHDL学习笔记第十六篇,记录使用SpinalHDL代码生成Verilog/VHDL代码的方法。
SpinalHDL学习笔记总纲链接如下:
目录:
1.从 SpinalHDL 组件生成 VHDL 和 Verilog
2.生成的 VHDL 和 Verilog
3.VHDL 和 Verilog 属性
1.从 SpinalHDL 组件生成 VHDL 和 Verilog
要 从 SpinalHDL 组 件 生 成 VHDL, 只 需 在 Scala main 函 数 中 调 用 SpinalVhdl(new
YourComponent) 即可。
生成 Verilog 完全相同,但用 SpinalVerilog 代替 SpinalVHDL。
import spinal.core._ // A simple component definition. class MyTopLevel extends Component { // Define some input/output signals. Bundle like a VHDL record or a Verilog␣ ,→struct. val io = new Bundle { val a = in Bool() val b = in Bool() val c = out Bool() } // Define some asynchronous logic. io.c := io.a & io.b } // This is the main function that generates the VHDL and the Verilog corresponding␣ ,→to MyTopLevel. object MyMain { def main(args: Array[String]) { SpinalVhdl(new MyTopLevel) SpinalVerilog(new MyTopLevel) } }
Note:SpinalVhdl 和 SpinalVerilog 可能需要创建组件类的多个实例,因此第一个参数不是Component 引用,而是返回新组件的函数。
2.生成的 VHDL 和 Verilog
如何将 SpinalHDL RTL 描述转换为 VHDL 和 Verilog 非常重要:
• Scala 中变量的名称将保留在 VHDL 和 Verilog 中。
• Scala 中的 Component 组件层次结构会保留在 VHDL 和 Verilog 中。
• Scala 中的 when 语句会生成为 VHDL 和 Verilog 中的 if 语句。
• Scala 中的 switch 语句在所有标准情况下都生成为 VHDL 和 Verilog 中的 case 语句。
组织:
当使用 VHDL 生成器时,所有模块都会生成到一个文件中,其中包含三个部分:
1. 包含所有 Enum 定义的包
2. 包含架构中所有元素使用函数的包
3. 您的设计所需的所有组件
当使用 Verilog 生成时,所有模块都会生成到一个文件中,其中包含两个部分:
1. 使用的所有枚举定义
2. 您的设计需要的所有模块
组合逻辑
Scala:
class TopLevel extends Component { val io = new Bundle { val cond = in Bool() val value = in UInt(4 bits) val withoutProcess = out UInt(4 bits) val withProcess = out UInt(4 bits) } io.withoutProcess := io.value io.withProcess := 0 when(io.cond) { switch(io.value) { is(U"0000") { io.withProcess := 8 } is(U"0001") { io.withProcess := 9 } default { io.withProcess := io.value+1 } } } }
VHDL:
entity TopLevel is port( io_cond : in std_logic; io_value : in unsigned(3 downto 0); io_withoutProcess : out unsigned(3 downto 0); io_withProcess : out unsigned(3 downto 0) ); end TopLevel; architecture arch of TopLevel is begin io_withoutProcess <= io_value; process(io_cond,io_value) begin io_withProcess <= pkg_unsigned("0000"); if io_cond = '1' then case io_value is when pkg_unsigned("0000") => io_withProcess <= pkg_unsigned("1000"); when pkg_unsigned("0001") => io_withProcess <= pkg_unsigned("1001"); when others => io_withProcess <= (io_value + pkg_unsigned("0001")); end case; end if; end process; end arch;
时序逻辑
Scala:
class TopLevel extends Component { val io = new Bundle { val cond = in Bool() val value = in UInt (4 bits) val resultA = out UInt(4 bits) val resultB = out UInt(4 bits) } val regWithReset = Reg(UInt(4 bits)) init(0) val regWithoutReset = Reg(UInt(4 bits)) regWithReset := io.value regWithoutReset := 0 when(io.cond) { regWithoutReset := io.value } io.resultA := regWithReset io.resultB := regWithoutReset }
VHDL:
entity TopLevel is port( io_cond : in std_logic; io_value : in unsigned(3 downto 0); io_resultA : out unsigned(3 downto 0); io_resultB : out unsigned(3 downto 0); clk : in std_logic; reset : in std_logic ); end TopLevel; architecture arch of TopLevel is signal regWithReset : unsigned(3 downto 0); signal regWithoutReset : unsigned(3 downto 0); begin io_resultA <= regWithReset; io_resultB <= regWithoutReset; process(clk,reset) begin if reset = '1' then regWithReset <= pkg_unsigned("0000"); elsif rising_edge(clk) then regWithReset <= io_value; end if; end process; process(clk) begin if rising_edge(clk) then regWithoutReset <= pkg_unsigned("0000"); if io_cond = '1' then regWithoutReset <= io_value; end if; end if; end process; end arch;
3.VHDL 和 Verilog 属性
在某些情况下,为设计中的某些信号提供属性以修改它们的综合方式很有用。
为此,可以对设计中的任何信号或存储器调用以下函数:
语法 | 描述 |
---|---|
addAttribute(name) | 添加一个名为 name 的布尔属性,并将给定值设置为 true |
addAttribute(name, | 添加一个字符串属性,并将给定的 name 设置为 value |
val pcPlus4 = pc + 4 pcPlus4.addAttribute("keep")
用 VHDL 生成声明:
attribute keep : boolean; signal pcPlus4 : unsigned(31 downto 0); attribute keep of pcPlus4: signal is true;
用 Verilog 生成声明:
(* keep *) wire [31:0] pcPlus4;