Code Monkey home page Code Monkey logo

spinalhdl's Introduction

About SpinalHDL

SpinalHDL is:

  • A language to describe digital hardware
  • Compatible with EDA tools, as it generates VHDL/Verilog files
  • Much more powerful than VHDL, Verilog, and SystemVerilog in its syntax and features
  • Much less verbose than VHDL, Verilog, and SystemVerilog
  • Not an HLS, nor based on the event-driven paradigm
  • Only generates what you asked it in a one-to-one way (no black-magic, no black box)
  • Not introducing area/performance overheads in your design (versus a hand-written VHDL/Verilog design)
  • Based on the RTL description paradigm, but can go much further
  • Allowing you to use Object-Oriented Programming and Functional Programming to elaborate your hardware and verify it
  • Free and can be used in the industry without any license

Links

English: Join the chat at https://gitter.im/SpinalHDL/SpinalHDL 中文: Join the chat at https://gitter.im/SpinalHDL-CN/community

Get it

SpinalHDL is simply a set of Scala libraries. Include them into your project and you're good to go! If you're unsure about what to do, simply clone one of our example projects (see links above).

SBT (Scala build tool)

scalaVersion := "2.11.12"

libraryDependencies ++= Seq(
  "com.github.spinalhdl" % "spinalhdl-core_2.11" % "latest.release",
  "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "latest.release",
  compilerPlugin("com.github.spinalhdl" % "spinalhdl-idsl-plugin_2.11" % "latest.release")
)

You can force SBT to pick a specific SpinalHDL version by replacing latest.release with a specific version. See the SpinalHDL SBT Template project's build.sbt file for a full SBT example.

Gradle

repositories {
	mavenCentral()
}

dependencies {
	compile group: 'com.github.spinalhdl', name: 'spinalhdl-core_2.11', version: '1.6.4'
	compile group: 'com.github.spinalhdl', name: 'spinalhdl-lib_2.11', version: '1.6.4'
}

Mill(Build Tool)

import mill._
import mill.scalalib._

object MySpinalModule extends ScalaModule {
  def scalaVersion = "2.11.12"

  def ivyDeps = Agg(
    ivy"com.github.spinalhdl::spinalhdl-core:1.6.4",
    ivy"com.github.spinalhdl::spinalhdl-lib:1.6.4",
  )

  def scalacPluginIvyDeps = Agg(ivy"com.github.spinalhdl::spinalhdl-idsl-plugin:1.6.4")
}

JAR

https://oss.sonatype.org/content/groups/public/com/github/spinalhdl/spinalhdl-core_2.11/
https://oss.sonatype.org/content/groups/public/com/github/spinalhdl/spinalhdl-lib_2.11/

The files are available on Maven as well.

Change logs

https://github.com/SpinalHDL/SpinalHDL/tags

License

The SpinalHDL core is using the LGPL3 license while SpinalHDL lib and others are using the MIT license. That's for the formalities. But there are some practical statements implied by those licenses:

Your freedoms are:

  • You can use SpinalHDL core and lib in your closed/commercial projects.
  • The generated RTL is yours (.vhd/.v files)
  • Your hardware description is yours (.scala files)

Your obligations (and my wish) are:

  • If you modify the SpinalHDL core (the compiler itself), please, share your improvements.

Also, SpinalHDL is provided "as is", without warranty of any kind.

spinalhdl's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spinalhdl's Issues

RFE: Change autocreated signal names from _zz_<number> to _zz_<number>_

Right now, autocreated signal names look this: _zz_<number>.

When there are many such signals, this makes it hard to search to the generated Verilog files with an editor, because a search for, say, _zz_3 will also match _zz_30, _zz_31 ...

This can be avoided if the signals are named _zz_3_ and _zz_30_ instead.

Tom

Default input values for Components?

Hi there,

Is there a way to declare inputs in a Component to have default values? For instance something like
val input = in UInt(8 bit) := 0

Right now that statement compiles in Scala but gives me a hierarchy error during HDL elaboration.

Tony

Optionaly Keep BitVector Unconstrained in the generated VHDL

In VHDL we can use unconstrained arrays, see for instance my synchronous fifo.

The array size are determined by the connected signals.

Is there a way to create an unconstrained BitVector?
Here is one of your examples:

class Counter(width : Int) extend Component{
  val io = new Bundle{
    val clear = in Bool
    val value = out UInt(width bit)
  }
  val register = Reg(UInt(width bit)) init(0)
  register := register + 1
  when(io.clear){
    register := 0
  }
  io.value := register
}

As a lazy programmer I would like to write:

class Counter extend Component{
  val io = new Bundle{
    val clear = in Bool
    val value = out UInt
  }
  val register = Reg(UInt) init(0)
  register := register + 1
  when(io.clear){
    register := 0
  }
  io.value := register
}

SpinalSim doesn't work on windows 10

Like the title, SpinalSim doesn't work on Windows 10 (StackTrace: https://pastebin.com/U7A46R1M). Now the code execute posix utilities(rm, mkdir, ecc..) to manipulate directories/files, but the commands windows 10 provide do not adhere to the posix standard. One example:

I think the correct thing to do is rewrite the file manipulation part with java/scala io library

Why 'Spinal'

Is it an acronym, or is it a biological reference ?

CPU Build Documentation incorrect...

the blob/ directory doesn't exist in the repo anymore... And it doesn't look like CoreQSysAvalon.scala file made it across or was stripped from the master branch. How does one set their HDL definitions to generate a QSys capable component?

wrong code in UInt isNotEquals

Note: I found this by skimming the source code. I don't understand all the surrounding code, and I haven't constructed a test case to verify that it's really wrong; but I'm fairly sure that it just can't be right.

In .../spinal/core/UInt.scala (from the current master branch), the isNotEquals function has the line:
case that: MaskedLiteral => that === this
(implementing not-equals in terms of equality). It seems like it should match the isNotEquals from SInt.scala, which instead has the line:
case that: MaskedLiteral => that =/= this

Axi4Lite interface at top level

Hi,
I'm new to the SpinalHDL / Scala language... As one of my first project attempts with SpinalHDL, Im trying to create an AXI4lite peripheral with the AXI IO at the top level, and i can't seem to get the syntax just right

here is what i have so far...

`class AxiPeriph(axiLite4Config : AxiLite4Config) extends Component {
val io = new Bundle {
val M0 = master(AxiLite4WriteOnly(axiLite4Config))
}
}

object MicronDmaVerilog {
def main(args: Array[String]) {
SpinalVerilog(new AxiPeriph(axiLite4Config = AxiLite4Config(
addressWidth = 32, dataWidth = 64
)))
}
}`

I get a number of errors looking like : NO DRIVER ON (toplevel/io_aw_aw_valid : out Bool), defined at...

Any help is greatly appreciated

Vec init(0)

I've been having a hard time finding the proper syntax/preferred method of initializing a Vec(Reg(Uint())), currently using the map function. Is init extended for arrays/multidimensional representations?

Issue warnings when BusSlaveFactory read multiple signals to the same address

Lets say I have multiple modules all of which I drive from the same bus. For all of them I use the same BusSlaveFactory. There should be a way to detect when reading multiple signals at the same address, as this is most commonly the case when mis-configuring base-addresses, addresses, or bitOffsets.

So for example this spinalHDL code:

val apbSlaveFactory = new Apb3SlaveFactory(io.apb3, 0)
val thermalCtrlDigitalBridge = thermalCtrlDigital.driveFrom(apbSlaveFactory, 0x00)
val thermalCtrlDigitalBridge_2 = thermalCtrlDigital_2.driveFrom(apbSlaveFactory, 0x04)

but I have made the mistake that one thermalCtrlDigital actually reads from addresses base+0x00 to base+0x07! This then results in the following data model on .printDataModel():

...
Address 0x4 :
  R[5:0] io_AIF_TCtrl_ref_current_DAC_o - ThermalControllerDigital: analog interface: Iset [5..0] 
  W[0:0]  - ThermalControllerDigital FSM control bit: start_locking 
  R[0:0]  - ThermalControllerDigital FSM control bit: start_locking 
  W[1:1]  - ThermalControllerDigital FSM control bit: start_ramp_heater 
  R[1:1]  - ThermalControllerDigital FSM control bit: start_ramp_heater 
  W[2:2]  - ThermalControllerDigital FSM control bit: stop_locking 
  R[2:2]  - ThermalControllerDigital FSM control bit: stop_locking 
  R[3:3] io_idle - ThermalControllerDigital FSM control bit: idle 
...

and in the following VHDL:

...
      when "00000100" =>
        if apbSlaveFactory_doWrite = '1' then
          zz_13 <= pkg_toStdLogic(true);
        end if;
        io_apb3_PRDATA(5 downto 0) <= zz_30;
        io_apb3_PRDATA(0 downto 0) <= pkg_toStdLogicVector(zz_7);
        io_apb3_PRDATA(1 downto 1) <= pkg_toStdLogicVector(zz_8);
        io_apb3_PRDATA(2 downto 2) <= pkg_toStdLogicVector(zz_9);
        io_apb3_PRDATA(3 downto 3) <= pkg_toStdLogicVector(zz_40);
...

The signal io_apb3_PRDATA gets overwritten in the process block which can hardly be any designers intention.

If somebody helps me setup a spinalHDL dev environment, I can try to implement an assertion.

RFE: Better error reporting on "val data = RegNext(data_old, enable)"

This code:

    val data_old = B("32'd0")
    val enable = True
    val data = RegNext(data_old, enable)

Gives the following error:

[info] [Progress] at 0.119 : Elaborate components
[error] Exception in thread "main" java.lang.Exception: Undefined assignment (toplevel/??? :  Bits[? bits]) := (toplevel/enable :  Bool)
[error] 	at spinal.core.BaseType.assignFromImpl(BaseType.scala:193)
[error] 	at spinal.core.Assignable$class.compositAssignFrom(Trait.scala:233)
[error] 	at spinal.core.BaseType.compositAssignFrom(BaseType.scala:52)
[error] 	at spinal.core.Data$class.initFrom(Data.scala:295)
[error] 	at spinal.core.BaseType.initFrom(BaseType.scala:52)
[error] 	at spinal.core.DataPrimitives$class.init(Data.scala:65)
[error] 	at spinal.core.DataPimper.init(Data.scala:92)
[error] 	at spinal.core.Reg$.apply(Reg.scala:36)
[error] 	at spinal.core.RegNext$.apply(Reg.scala:49)
[error] 	at mr1.Fetch.delayedEndpoint$mr1$Fetch$1(Fetch.scala:136)

The last usable line in the code Fetch.scala:136 which points to the start of the Component.

Is there a way to be more precise with these class of errors? So not just this specific error but anything where an error points at a general class without telling the exact line in the code should be avoided.

Tom

"32'h0" and "32'b0" resolve to a 4 bit and 1 bit signal.

This following code results in an error:

      var test = Bits(32 bits)
      test := "32'h0"

SpinalHDL assumes that "32'h0" is a 4 bit signal instead of 32 bits.

IMO, this violates the principle of least surprise.

In Verilog, the 32 has priority over the number digits behind the 'h'. I think that the Verilog way makes more sense than the current behavior, which makes the '32' essentially useless (except when using "32'd0").

Tom

Problem creating Pinsec

I have a problem creating Pinsec:

$ cat MS6P.scala
import spinal.core._
import spinal.lib._
import spinal.lib.soc.pinsec._
object Pinsec{
  def main(args: Array[String]) {
    SpinalVerilog(new Pinsec(100 MHz))
  }
}
$ cat build.sbt
name := "SpinalBaseProject"
version := "1.0"
scalaVersion := "2.11.6"
EclipseKeys.withSource := true
libraryDependencies ++= Seq(
  "com.github.spinalhdl" % "spinalhdl-core_2.11" % "latest.release",
  "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "latest.release"
)
$ scala -version
Scala code runner version 2.11.6 -- Copyright 2002-2013, LAMP/EPFL
$ sbt about
[info] Loading project definition from /.../SpinalBaseProject/project
[info] Set current project to SpinalBaseProject (in build file:/.../SpinalBaseProject/)
[info] This is sbt 0.13.12
[info] The current project is {file:/.../SpinalBaseProject/}spinalbaseproject 1.0
[info] The current project is built against Scala 2.11.6
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, com.typesafe.sbteclipse.plugin.EclipsePlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.6
$ sbt run
[info] Loading project definition from /.../project
[info] Set current project to SpinalBaseProject (in build file:/.../projects/SpinalBaseProject/)
[info] Compiling 2 Scala sources to /.../projects/SpinalBaseProject/target/scala-2.11/classes...
[error] /.../projects/SpinalBaseProject/MS6P.scala:6: too many arguments for constructor Pinsec: ()spinal.lib.soc.pinsec.Pinsec
[error]     SpinalVerilog(new Pinsec(100 MHz))
[error]                    ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed 4-Sep-2016 6:00:14 PM

When I remove argument 100 MHz from Pinsec constructor I get more less expected runtime error:

...
[error] (run-main-0) spinal.core.SpinalExit: 
[error] 
[error] 
[error] You are trying to get the frequency of a ClockDomain that dosen't know it
...

Can you please advice what I am doing wrong?

Describe testbench from within Spinal

This would be a very nice feature. One would be able to describe time variation with a relationship to a signal and this would automatically generate a TB for simulation. For instance:

val a := some multibit signal as input 
val b := some other signal related to a through a component

tb{
    a := a + 1 every 10 uS
    assert ( something about b that changes according to a)
} with clock @ 5 MHz

Just an idea you know

Universal reset

Reset generation for synchronous blocks should be configurable since support in target architecture will vary.

I think this 3 cases (and combinations) should be supported:

  • asynchronous reset (like it is at this time)
...
signal test : std_ulogic;
...
process(reset, clock)
    if reset = '1' then
        test <= '0';
    elsif rising_edge(clock) then
        test <= not test;
    end if;
end process;
  • synchronous reset
...
signal test : std_ulogic;
...
process(clock)
    if rising_edge(clock) then
        test <= not test;
        if reset = '1' then
            test <= '0';
        end if;
    end if;
end process;
  • no reset (can save a lot of routing resource in FPGA).
...
signal test : std_ulogic := '0';
...
process(clock)
    if rising_edge(clock) then
        test <= not test;
    end if;
end process;

RFE: Reduce unnecessary intermediate signals assignments

This is probably a very fundamental request, but I'm going to propose it any way.

Right now, SpinalHDL creates tons of intermediate zz* signals that are not strictly required and that make debugging a whole lot more difficult than necessary.

Here's a typical example:

  assign rvfi_valid = _zz_178;
  assign rvfi_halt = _zz_179;
  ...
  always @ (*) begin
    _zz_178 = writeBack_arbitration_isFiring;
    rvfi_trap = 1'b0;
    _zz_179 = 1'b0;
    if(_zz_110)begin
      _zz_178 = 1'b1;
      rvfi_trap = 1'b1;
      _zz_179 = 1'b1;
    end
    if(writeBack_FormalPlugin_haltFired)begin
      _zz_178 = 1'b0;
    end
  end
  ...
      if((_zz_178 && _zz_179))begin
        writeBack_FormalPlugin_haltFired <= 1'b1;
      end

Except for their declaration, these are the only places where _zz_178 and _zz_179 are used.

The problem, of course, is that one has to page through the code to understand the last 'if' statement is really nothing more than:

      if((rvfi_valid && rvfi_halt))begin
        writeBack_FormalPlugin_haltFired <= 1'b1;
      end

and that the whole code can be rewritten like this:

  always @ (*) begin
    rvfi_valid = writeBack_arbitration_isFiring;
    rvfi_trap = 1'b0;
    rvfi_halt = 1'b0;
    if(_zz_110)begin
      rvfi_valid = 1'b1;
      rvfi_trap = 1'b1;
      rvfi_halt = 1'b1;
    end
    if(writeBack_FormalPlugin_haltFired)begin
      rvfi_valid = 1'b0;
    end
  end
  ...
      if((rvfi_valid && rvfi_halt ))begin
        writeBack_FormalPlugin_haltFired <= 1'b1;
      end

Not all signasl can obviously be reduced that easily (see _zz_110), but I'll take whatever I can get as long as it reduced the zz soup.

However, speaking about _zz_110, there's this:

  assign _zz_105 = 1'b0;
  ..
  always @ (posedge clk) begin
    if(reset) begin
      ..
      _zz_106 <= _zz_105;
      _zz_107 <= _zz_105;
      _zz_108 <= _zz_105;
      _zz_109 <= _zz_105;
      _zz_110 <= _zz_105;
      ..
    end else begin
      ..
      _zz_106 <= writeBack_FormalPlugin_haltRequest;
      _zz_107 <= _zz_106;
      _zz_108 <= _zz_107;
      _zz_109 <= _zz_108;
      _zz_110 <= _zz_109;

The trivial renaming step would result in _zz_105 being eliminated completely:

  always @ (posedge clk) begin
    if(reset) begin
      ..
      _zz_106 <= 1'b0;
      _zz_107 <= 1'b0;
      _zz_108 <= 1'b0;
      _zz_109 <= 1'b0;
      _zz_110 <= 1'b0;
      ..
    end else begin
      ..
      _zz_106 <= writeBack_FormalPlugin_haltRequest;
      _zz_107 <= _zz_106;
      _zz_108 <= _zz_107;
      _zz_109 <= _zz_108;
      _zz_110 <= _zz_109;

And a slightly smarter renaming post-processing step could do the following (assuming there won't be a name clash) :

  always @ (posedge clk) begin
    if(reset) begin
      ..
      writeBack_FormalPlugin_haltRequest_p1 <= 1'b0;
      writeBack_FormalPlugin_haltRequest_p2 <= 1'b0;
      writeBack_FormalPlugin_haltRequest_p3 <= 1'b0;
      writeBack_FormalPlugin_haltRequest_p4 <= 1'b0;
      writeBack_FormalPlugin_haltRequest_p5 <= 1'b0;
      ..
    end else begin
      ..
      writeBack_FormalPlugin_haltRequest_p1 <= writeBack_FormalPlugin_haltRequest;
      writeBack_FormalPlugin_haltRequest_p2 <= writeBack_FormalPlugin_haltRequest_p1;
      writeBack_FormalPlugin_haltRequest_p3 <= writeBack_FormalPlugin_haltRequest_p2;
      writeBack_FormalPlugin_haltRequest_p4 <= writeBack_FormalPlugin_haltRequest_p3;
      writeBack_FormalPlugin_haltRequest_p5 <= writeBack_FormalPlugin_haltRequest_p4;

I don't understand the SpinalHDL framework well enough to know if this kind of deriving of names is at all possible (e.g. as a post-processing step), but it would make it so much easier to debug.
Right now, making a single change will make all the zz signals in a .gtkw file useless.

Tom

Problem generating vcd file

whenever I use the whitWave "option" with SpinalSim, I get this error message: Complete log

../Wishbonetest_verilatorSim/VWishbonetest__spinalWrapper.cpp: In constructor ‘Wrapper::Wrapper(const char*)’:
../Wishbonetest_verilatorSim/VWishbonetest__spinalWrapper.cpp:135:17: error: ‘string’ was not declared in this scope
       tfp.open((string("Wishbonetest_verilatorSim/VWishbonetest_") + name + ".vcd").c_str());
                 ^~~~~~
../Wishbonetest_verilatorSim/VWishbonetest__spinalWrapper.cpp:135:17: note: suggested alternatives:
In file included from /usr/include/c++/7.2.1/string:39:0,
                 from /usr/share/verilator/include/verilated_vcd_c.h:29,
                 from ../Wishbonetest_verilatorSim/VWishbonetest__spinalWrapper.cpp:5:
/usr/include/c++/7.2.1/bits/stringfwd.h:74:33: note:   ‘std::__cxx11::string’
   typedef basic_string<char>    string;
                                 ^~~~~~
/usr/include/c++/7.2.1/bits/stringfwd.h:74:33: note:   ‘std::__cxx11::string’
make: *** [VWishbonetest.mk:67: VWishbonetest__spinalWrapper.o] Error 1
make: *** Waiting for unfinished jobs....

I'm using SpinalHDL version 1.0.2 and verilator 3.916 2017-11-25 rev verilator_3_914-65-g0478dbd

StreamArbiter locked should clear when fire assert.

Hi,

diff --git a/lib/src/main/scala/spinal/lib/Stream.scala b/lib/src/main/scala/spinal/lib/Stream.scala
index 54860c35..c9c3e41a 100644
--- a/lib/src/main/scala/spinal/lib/Stream.scala
+++ b/lib/src/main/scala/spinal/lib/Stream.scala
@@ -397,14 +397,14 @@ object StreamArbiter {
     def transactionLock(core: StreamArbiter[_]) = new Area {
       import core._
       locked setWhen(io.output.valid)
-      locked.clearWhen(io.output.ready)
+      locked.clearWhen(io.output.fire)
     }
 
     def fragmentLock(core: StreamArbiter[_]) = new Area {
       val realCore = core.asInstanceOf[StreamArbiter[Fragment[_]]]
       import realCore._
       locked setWhen(io.output.valid)
-      locked.clearWhen(io.output.ready && io.output.last)
+      locked.clearWhen(io.output.fire && io.output.last)
     }
   }
 }

RFE: Make switch statement optimized for one-hot encoded arguments

Current code:

        object PcState extends SpinalEnum(binaryOneHot) {
            val Idle           = newElement()
            val WaitReqReady   = newElement()
            val WaitRsp        = newElement()
            val WaitJumpDone   = newElement()
            val WaitStallDone  = newElement()
        }
...
    val instr_final = (pc.cur_state === pc.PcState.WaitStallDone) ? instr_r     | instr
...
        switch(cur_state){
            is(PcState.Idle){
...

This generates the following verilog:

`define PcState_defaultEncoding_type [4:0]
`define PcState_defaultEncoding_Idle 5'b00001
`define PcState_defaultEncoding_WaitReqReady 5'b00010
`define PcState_defaultEncoding_WaitRsp 5'b00100
`define PcState_defaultEncoding_WaitJumpDone 5'b01000
`define PcState_defaultEncoding_WaitStallDone 5'b10000
...
// GOOD:
  assign instr_final = (((pc_cur_state & `PcState_defaultEncoding_WaitStallDone) != 5'b00000) ? instr_r : instr);
// BAD
    case(pc_cur_state)
      `PcState_defaultEncoding_Idle : begin

The regular compare operation is optimized for one-hot encoding, but the switch statement compares the full vector.
Ideally, it should generate something like this:

(* parallel case *) 
case(1) // synopsys parallel_case
    ((pc_state & `PcState_defaultEncoding_Idle) != 5'b00000): begin
...

The (* parallel case *) is supported by some, but not all, synthesis tools. The same is true for // synopsys parallel_case. So you need both. It's seriously annoying.

parallel_case usage is usually highly discouraged, but one-hot encoded case statements are an exception. From the paper:

Guideline: only use full_case parallel_case to optimize onehot FSM designs.

[reworkDev] Initial statements outputed in Verilog RTL

Hi,
first of all, I don't know how stable is the reworkDev branch supposed to be, so if the below described issue is a known problem, please close this ticket.
I tried the reworkDev branch and I like very much how the new Verilog backend behaves, since it produces less verbose code. Nevertheless, I found a small issue: when a bit vector is assigned bit-wise, initial statements are produced in the outputed RTL. These statements are not synthesizable, so they are ignored by the synthesis.
Here is an example

  val io = new Bundle {
    val obits = out Bits(2 bit)
  }
  io.obits(0) := True
  io.obits(1) := False

This generates the following Verilog code

  initial begin
    io_obits[0] = 1'b1;
    io_obits[1] = 1'b0;
  end

which, as I said, is behavioral code, not RTL.
A possible way to fix it would be to use the always @* statement instead of the initial, but this would generate issues in simulation, since the always @* is not evaluated at time zero. The always_comb statement solves this issue, but it is a SystemVerilog statement, not Verilog (I don't know whether you want to switch to SystemVerilog as RTL language). Probably the best way to solve it is to use 'assign' statements:

  assign io_obits[0] = 1'b1;
  assign io_obits[1] = 1'b0;

I tried to identify the issue, and it seems related to line 347 of ComponentEmiterVerilog.scala (SHA ID 5dc53c5). Given my very low knowledge of Scala, I can't propose a fix.

Axi4SpecRenamer can not work with Axi4ReadOnly/WriteOnly.

val cmd = master(Axi4ReadOnly(cmdg.getAxi4Config))
....
Axi4SpecRenamer(io.cmd)

then I got error message.

[error] /home/steve/src/ssd/arcdome/src/main/scala/dma.scala:64: type mismatch;
[error] found : spinal.lib.bus.amba4.axi.Axi4ReadOnly
[error] required: spinal.lib.bus.amba4.axi.Axi4
[error] Axi4SpecRenamer(io.cmd)

Thanks.

BlackBox pararam assignment with width-check

Hello,
since Verilog parameters can have a width (in bits), I would like to be able to assign them as follows, to have a check on the width of the value assigned to them

// Definition
class bboxedm extends BlackBox {
  val generic = new Generic {
    val intparam = UInt(8 bit)
  }
  val io = new Bundle {
    // ...
  }.setName("")
}

// Instantiation
val bboxedm_inst = new bboedm
bboxedm_inst.generic.intparam := U(7, 8 bit)
// ...

Doing this, if I assign to the parameter a value of different size or a value which does not fit, I get an error.
What do you think?
Or is there already a way to check the parameter value width?
Thanks.

[Verilog Backend] Lint issues

Hi,
I am reporting some Linting issues of the Verilog backend.
These are neither functional issues nor syntax issues, but, since Linting is often used to evaluate the RTL quality, in my opinion, it would be good to solve them. Without solving those, most of the digital designers will not have confidence in the RTL generated by Spinal.

Width mismatch
sometimes (when we resize a signal) we can have assignments like this:

wire [31:0] a;
wire b;
assign a = b;

this is usually considered as a lint issue, since there is a mismatch on the signal widths.
Would be nice to to have some zero padding

assign a = {31'd0, b};

I guess the opposite scenario (assign b = a with a wider than b) cannot happen, right?

Signal assigned by mutiple non-blocking assignments
When we have source code like the following

val flop = Reg(Bool) init(False)
flop := io.a
when (io.e) {
  flop := io.d
}

the generated Verilog RTL looks like follows

always @(posedge clk or negedge reset)
begin
  if (reset) begin
    flop <= 1'b0;
  end else begin
    flop <= io_a;
    if (io_e) begin
      flop <= io_d;
    end
  end
end

This kind of coding, where the same variable is assigned by multiple non-blocking assignments (<=), is considered as a bad practice, even if it is allowed by the Verilog language. The reason for this (as you probably already know) is that non-blocking assignments are executed in 2 steps: evaluation and update, this means that in normal situations they can be re-ordered; in other words

always @(posedge clk)
begin
  a <= b;
  b <= a;
end

is equivalent to

always @(posedge clk)
begin
  b <= a;
  a <= b;
end

Now, the Verilog standard states that non-blocking assignments assigning the same variable cannot be reordered and their order must be taken into account. So the generated Verilog describes the desired behaviour (other than being syntactically correct); nevertheless, this coding is considered as a bad practice. I would generate Verilog code as follows:

always @*
begin
  flop_nxt = io_a;
  if (io_e) begin
    flop_nxt = io_d;
  end
end

always @(posedge clk or negedge reset)
begin
  if (reset) begin
    flop <= 1'b0;
  end else begin
    flop <= flop_nxt;
  end
end

RFE: Option to generate ascii version of an enum

When you have an Enum and you're using Verilog, there is no way to see the textual value of the Enum in the waveforms.

There should be an option to generate an additional helper signal that has the ascii version of the signal.

Something like this:

object MyState extends SpinalEnum(binaryOneHot) {
    val Idle = newElement()
    val Active = newElement()
}
...
   val cur_state = MyState().decodeAsText

Should generate something like this:

`define MyState_binary_one_hot_Idle 4'b0001
...
reg [3:0] cur_state;
...
`ifndef SYNTHESIS
reg [0:255]  cur_state_txt;

case(1'b1)
   ((cur_state & MyState_binary_one_hot_Idle) != 4'b0000): cur_state_txt = "Idle";
   ...
    default: cur_state_txt = "<Unknown>"
endcase
`endif

You can then add cur_state_txt to gtkwave and use the ASCII format to display the signal as "Idle" etc.

The annoying extra `.` in `.elseWhen` and `.otherwise`

See the following example:

when(cond1){
  //
}.elsewhen(cond2){
  //
}.otherwise{
  //
}

I wish to write the above without the extra .

when(cond1){
  //
} elsewhen(cond2){
  //
} otherwise{
  //
}

I investigated the matter on the scala contributors gitter channel and it turns out this may be a Scalac parser bug.

Follow issue scala/bug#8859 . If resolved, it may solve this issue for Spinal.
I also created a ticked for dotty, which has a similar issue. scala/scala3#3737

VHDL generation does not appear to produce vaild results with Attributes added.

From a generator pass of Briey:

architecture arch of VexRiscv is
attribute verilator public : boolean;

Here's the complaint from Quartus:

Error (10500): VHDL syntax error at bt_soc2.vhd(5525) near text "public"; expecting "of"

Another oops from generated VHDL:

signal writeBack_RegFilePlugin_regFileWrite_valid : std_logic;
attribute verilator public of writeBack_RegFilePlugin_regFileWrite_valid: signal is true;

...and the complaint from Quartus:

Error (10500): VHDL syntax error at bt_soc2.vhd(5685) near text "public"; expecting "of"

Looks like something's injecting "public" in the mix there and at least Quartus doesn't like it.

Cross platform toplevel pin mapping definition

For exemple, Xilinx and Altera have their own file format to specify mapping between design pins and package pins (+ specify pin technologies, current, terminaison, ...)

It could be great to have a scala DSL to specify them without having to worry about the specific syntax of the target EDA.

cdc check for multi-clock black box

Hi,
we do ASIC designs with many (>300) clock domains.
Currently we develop in SystemVerilog.
We don't have a methodology to automatically detect clock-domain-crossings better than following the rule of "don't do mistakes".
To benefit from SpinalHDLs ability to assert on clock-domain-crossings we have the idea to, in the first step, convert the toplevel to SpinalHDL and import all existing sub-modules as black boxes.
Some of the sub-modules have multiple clocks inputs.
I know from the SpinalHDL black-box documentation the mapClockDomain() method, but i assume that this sets the domain membership for all inputs/outputs.

I'd like to know whether it's possible to assign ports of a black-box individually to clock domains?

I'm fully aware that a manual mapping is error prone but still better than what we have today (nothing).

If this is already possible please provide a pointer to an example/docu.

If this is not already possible please treat my question as a feature proposal because i think this area of clock-domain-crossing checks could be a good story to push SpinalHDL into old-styled design teams.

Thank you for your support!

Best regards,
Klaus

Documentation Feature Request: Documentation for QSysify...

While I realize it's not a full priority, this tool could be very powerful overall- with a comparable thing for each vendor's or Open Source project's macroblock assembly tool.

Not all potential prospective users can embrace SpinalHDL directly. (I know, they should, but...)

Some are stuck with using Verilog or VHDL because of management edict, etc. while they CAN use it as a subsystem/macro building tool to generate valid RTL of the same two there. (My current use...)

For some, they'll just absorb the Verilog or VHDL. Some would like to be able to crank out a QSys capable set of files for what function macros they design with SpinalHDL.

I've done some experimentation with the VexRiscv CPU core and QSysify. It's not obvious whether the issues I encountered are functionality needing to be added or told what to do. Part of this is due to a lack of clear instructions on some of it's use.

Is it possible to tell QSysify to use something other than a Conduit for an interface?

  • Some things are legitimately Conduits.
  • Some things are actually a valid bus under Avalon Interconnect rules now. (AXI4 counts as a valid bus)

The problem right now is that if you QSysify the VexRiscv as a full build-out, it Conduits everything other than the clocks and the resets. Less than useful- and not clear if it's an omission on the user's part or a design thing needing to be worked out as a real feature enhancement. You can specify axi4, ahb, amb as bus types in the latest versions of QSys for the TCL-spec files and it will understand and use it properly as to whichever it was you specified.

Clear basic documentation on driving this functionality would help a lot on this and let people help you grow it into even more powerful/capable abilities.

Synthesis error in FSM with Synplify

Synthesizing a FSM with Synplify yields an error message as can be seen in the line starting with @E in the log file below. The SpinalHDL code used is the one of the Style A example on the State machine page of the SpinlDoc. The line causing the Type binding failed error is the first when statement in the fsm_stateReg case:

case fsm_stateReg is
      when pkg_enum.fsm_stateA =>

Synthesis Error Log

#Build: Synplify Pro G-2012.09M-SP1 , Build 013R, Feb 15 2013
#install: C:\eda\Microsemi\Libero_v11.0\Synopsys\synplify_G201209MSP1
#OS: Windows 7 6.1
#Hostname: WE5370

#Implementation: synthesis

$ Start of Compile
#Fri Sep 29 14:19:04 2017

Synopsys VHDL Compiler, version comp201209rcp1, Build 245R, built Feb 20 2013
@N|Running in 64-bit mode
Copyright (C) 1994-2012 Synopsys, Inc. This software the associated documentation are confidential and proprietary to Synopsys, Inc. Your use or disclosure of this software subject to the terms and conditions of a written license agreement between you, or your company, and Synopsys, Inc.

@N: CD720 :"C:\eda\Microsemi\Libero_v11.0\Synopsys\synplify_G201209MSP1\lib\vhd\std.vhd":123:18:123:21|Setting time resolution to ns
@N:"E:\projects\CubeSatCOM\dev\implementation\spinal\SpinalBaseProject\FSM.vhd":408:7:408:9|Top entity is set to FSM.
VHDL syntax check successful!
@N: CD630 :"E:\projects\CubeSatCOM\dev\implementation\spinal\SpinalBaseProject\FSM.vhd":408:7:408:9|Synthesizing work.fsm.arch 
@N: CD233 :"E:\projects\CubeSatCOM\dev\implementation\spinal\SpinalBaseProject\FSM.vhd":10:26:10:27|Using sequential encoding for type fsm_enumdefinition
@E: CD400 :"E:\projects\CubeSatCOM\dev\implementation\spinal\SpinalBaseProject\FSM.vhd":442:11:442:18|Type binding failed
@END
Process took 0h:00m:01s realtime, 0h:00m:01s cputime
# Fri Sep 29 14:19:05 2017

###########################################################]

VHDL source file

-- Generator : SpinalHDL v0.10.15    git head : 28b16cb90aa742a1126bc60a447a61f1d211f6fc
-- Date      : 29/09/2017, 14:17:03
-- Component : FSM

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;

package pkg_enum is
  type fsm_enumDefinition is (boot,fsm_stateA,fsm_stateB,fsm_stateC);
  type fsm_enumDefinition_debug is (XXX,boot,fsm_stateA,fsm_stateB,fsm_stateC);

  function pkg_mux (sel : std_logic;one : fsm_enumDefinition;zero : fsm_enumDefinition) return fsm_enumDefinition;
  function pkg_toStdLogicVector_native (value : fsm_enumDefinition) return std_logic_vector;
  function pkg_tofsm_enumDefinition_native (value : std_logic_vector(1 downto 0)) return fsm_enumDefinition;
end pkg_enum;

package body pkg_enum is
  function pkg_mux (sel : std_logic;one : fsm_enumDefinition;zero : fsm_enumDefinition) return fsm_enumDefinition is
  begin
    if sel = '1' then
      return one;
    else
      return zero;
    end if;
  end pkg_mux;

  function pkg_tofsm_enumDefinition_native (value : std_logic_vector(1 downto 0)) return fsm_enumDefinition is
  begin
    case value is
      when "00" => return boot;
      when "01" => return fsm_stateA;
      when "10" => return fsm_stateB;
      when "11" => return fsm_stateC;
      when others => return boot;
    end case;
  end;
  function pkg_toStdLogicVector_native (value : fsm_enumDefinition) return std_logic_vector is
  begin
    case value is
      when boot => return "00";
      when fsm_stateA => return "01";
      when fsm_stateB => return "10";
      when fsm_stateC => return "11";
      when others => return "00";
    end case;
  end;
end pkg_enum;


library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

package pkg_scala2hdl is
  function pkg_extract (that : std_logic_vector; bitId : integer) return std_logic;
  function pkg_extract (that : std_logic_vector; base : unsigned; size : integer) return std_logic_vector;
  function pkg_cat (a : std_logic_vector; b : std_logic_vector) return std_logic_vector;
  function pkg_extract (that : unsigned; bitId : integer) return std_logic;
  function pkg_extract (that : unsigned; base : unsigned; size : integer) return unsigned;
  function pkg_cat (a : unsigned; b : unsigned) return unsigned;
  function pkg_extract (that : signed; bitId : integer) return std_logic;
  function pkg_extract (that : signed; base : unsigned; size : integer) return signed;
  function pkg_cat (a : signed; b : signed) return signed;


  function pkg_mux (sel : std_logic;one : std_logic;zero : std_logic) return std_logic;
  function pkg_mux (sel : std_logic;one : std_logic_vector;zero : std_logic_vector) return std_logic_vector;
  function pkg_mux (sel : std_logic;one : unsigned;zero : unsigned) return unsigned;
  function pkg_mux (sel : std_logic;one : signed;zero : signed) return signed;


  function pkg_toStdLogic (value : boolean) return std_logic;
  function pkg_toStdLogicVector (value : std_logic) return std_logic_vector;
  function pkg_toUnsigned(value : std_logic) return unsigned;
  function pkg_toSigned (value : std_logic) return signed;
  function pkg_stdLogicVector (lit : std_logic_vector) return std_logic_vector;
  function pkg_unsigned (lit : unsigned) return unsigned;
  function pkg_signed (lit : signed) return signed;

  function pkg_resize (that : std_logic_vector; width : integer) return std_logic_vector;
  function pkg_resize (that : unsigned; width : integer) return unsigned;
  function pkg_resize (that : signed; width : integer) return signed;

  function pkg_extract (that : std_logic_vector; high : integer; low : integer) return std_logic_vector;
  function pkg_extract (that : unsigned; high : integer; low : integer) return unsigned;
  function pkg_extract (that : signed; high : integer; low : integer) return signed;

  function pkg_shiftRight (that : std_logic_vector; size : natural) return std_logic_vector;
  function pkg_shiftRight (that : std_logic_vector; size : unsigned) return std_logic_vector;
  function pkg_shiftLeft (that : std_logic_vector; size : natural) return std_logic_vector;
  function pkg_shiftLeft (that : std_logic_vector; size : unsigned) return std_logic_vector;

  function pkg_shiftRight (that : unsigned; size : natural) return unsigned;
  function pkg_shiftRight (that : unsigned; size : unsigned) return unsigned;
  function pkg_shiftLeft (that : unsigned; size : natural) return unsigned;
  function pkg_shiftLeft (that : unsigned; size : unsigned) return unsigned;

  function pkg_shiftRight (that : signed; size : natural) return signed;
  function pkg_shiftRight (that : signed; size : unsigned) return signed;
  function pkg_shiftLeft (that : signed; size : natural) return signed;
  function pkg_shiftLeft (that : signed; size : unsigned) return signed;

  function pkg_rotateLeft (that : std_logic_vector; size : unsigned) return std_logic_vector;
end  pkg_scala2hdl;

package body pkg_scala2hdl is
  function pkg_extract (that : std_logic_vector; bitId : integer) return std_logic is
  begin
    return that(bitId);
  end pkg_extract;


  function pkg_extract (that : std_logic_vector; base : unsigned; size : integer) return std_logic_vector is
   constant elementCount : integer := (that'length-size)+1;
   type tableType is array (0 to elementCount-1) of std_logic_vector(size-1 downto 0);
   variable table : tableType;
  begin
    for i in 0 to elementCount-1 loop
      table(i) := that(i + size - 1 downto i);
    end loop;
    return table(to_integer(base));
  end pkg_extract;


  function pkg_cat (a : std_logic_vector; b : std_logic_vector) return std_logic_vector is
    variable cat : std_logic_vector(a'length + b'length-1 downto 0);
  begin
    cat := a & b;
    return cat;
  end pkg_cat;


  function pkg_extract (that : unsigned; bitId : integer) return std_logic is
  begin
    return that(bitId);
  end pkg_extract;


  function pkg_extract (that : unsigned; base : unsigned; size : integer) return unsigned is
   constant elementCount : integer := (that'length-size)+1;
   type tableType is array (0 to elementCount-1) of unsigned(size-1 downto 0);
   variable table : tableType;
  begin
    for i in 0 to elementCount-1 loop
      table(i) := that(i + size - 1 downto i);
    end loop;
    return table(to_integer(base));
  end pkg_extract;


  function pkg_cat (a : unsigned; b : unsigned) return unsigned is
    variable cat : unsigned(a'length + b'length-1 downto 0);
  begin
    cat := a & b;
    return cat;
  end pkg_cat;


  function pkg_extract (that : signed; bitId : integer) return std_logic is
  begin
    return that(bitId);
  end pkg_extract;


  function pkg_extract (that : signed; base : unsigned; size : integer) return signed is
   constant elementCount : integer := (that'length-size)+1;
   type tableType is array (0 to elementCount-1) of signed(size-1 downto 0);
   variable table : tableType;
  begin
    for i in 0 to elementCount-1 loop
      table(i) := that(i + size - 1 downto i);
    end loop;
    return table(to_integer(base));
  end pkg_extract;


  function pkg_cat (a : signed; b : signed) return signed is
    variable cat : signed(a'length + b'length-1 downto 0);
  begin
    cat := a & b;
    return cat;
  end pkg_cat;



  -- unsigned shifts
  function pkg_shiftRight (that : unsigned; size : natural) return unsigned is
  begin
    if size >= that'length then
      return "";
    else
      return shift_right(that,size)(that'high-size downto 0);
    end if;
  end pkg_shiftRight;

  function pkg_shiftRight (that : unsigned; size : unsigned) return unsigned is
  begin
    return shift_right(that,to_integer(size));
  end pkg_shiftRight;

  function pkg_shiftLeft (that : unsigned; size : natural) return unsigned is
  begin
    return shift_left(resize(that,that'length + size),size);
  end pkg_shiftLeft;

  function pkg_shiftLeft (that : unsigned; size : unsigned) return unsigned is
  begin
    return shift_left(resize(that,that'length + 2**size'length - 1),to_integer(size));
  end pkg_shiftLeft;


  -- std_logic_vector shifts
  function pkg_shiftRight (that : std_logic_vector; size : natural) return std_logic_vector is
  begin
    return std_logic_vector(pkg_shiftRight(unsigned(that),size));
  end pkg_shiftRight;

  function pkg_shiftRight (that : std_logic_vector; size : unsigned) return std_logic_vector is
  begin
    return std_logic_vector(pkg_shiftRight(unsigned(that),size));
  end pkg_shiftRight;

  function pkg_shiftLeft (that : std_logic_vector; size : natural) return std_logic_vector is
  begin
    return std_logic_vector(pkg_shiftLeft(unsigned(that),size));
  end pkg_shiftLeft;

  function pkg_shiftLeft (that : std_logic_vector; size : unsigned) return std_logic_vector is
  begin
    return std_logic_vector(pkg_shiftLeft(unsigned(that),size));
  end pkg_shiftLeft;

  -- signed shifts
  function pkg_shiftRight (that : signed; size : natural) return signed is
  begin
    return signed(pkg_shiftRight(unsigned(that),size));
  end pkg_shiftRight;

  function pkg_shiftRight (that : signed; size : unsigned) return signed is
  begin
    return shift_right(that,to_integer(size));
  end pkg_shiftRight;

  function pkg_shiftLeft (that : signed; size : natural) return signed is
  begin
    return signed(pkg_shiftLeft(unsigned(that),size));
  end pkg_shiftLeft;

  function pkg_shiftLeft (that : signed; size : unsigned) return signed is
  begin
    return signed(pkg_shiftLeft(unsigned(that),size));
  end pkg_shiftLeft;

  function pkg_rotateLeft (that : std_logic_vector; size : unsigned) return std_logic_vector is
  begin
    return std_logic_vector(rotate_left(unsigned(that),to_integer(size)));
  end pkg_rotateLeft;

  function pkg_extract (that : std_logic_vector; high : integer; low : integer) return std_logic_vector is
    variable temp : std_logic_vector(high-low downto 0);
  begin
    temp := that(high downto low);
    return temp;
  end pkg_extract;

  function pkg_extract (that : unsigned; high : integer; low : integer) return unsigned is
    variable temp : unsigned(high-low downto 0);
  begin
    temp := that(high downto low);
    return temp;
  end pkg_extract;

  function pkg_extract (that : signed; high : integer; low : integer) return signed is
    variable temp : signed(high-low downto 0);
  begin
    temp := that(high downto low);
    return temp;
  end pkg_extract;

  function pkg_mux (sel : std_logic;one : std_logic;zero : std_logic) return std_logic is
  begin
    if sel = '1' then
      return one;
    else
      return zero;
    end if;
  end pkg_mux;

  function pkg_mux (sel : std_logic;one : std_logic_vector;zero : std_logic_vector) return std_logic_vector is
    variable ret : std_logic_vector(zero'range);  begin
    if sel = '1' then
      ret := one;
    else
      ret := zero;
    end if;
    return ret;  end pkg_mux;

  function pkg_mux (sel : std_logic;one : unsigned;zero : unsigned) return unsigned is
    variable ret : unsigned(zero'range);  begin
    if sel = '1' then
      ret := one;
    else
      ret := zero;
    end if;
    return ret;  end pkg_mux;

  function pkg_mux (sel : std_logic;one : signed;zero : signed) return signed is
    variable ret : signed(zero'range);  begin
    if sel = '1' then
      ret := one;
    else
      ret := zero;
    end if;
    return ret;  end pkg_mux;

  function pkg_toStdLogic (value : boolean) return std_logic is
  begin
    if value = true then
      return '1';
    else
      return '0';
    end if;
  end pkg_toStdLogic;

  function pkg_toStdLogicVector (value : std_logic) return std_logic_vector is
    variable ret : std_logic_vector(0 downto 0);
  begin
    ret(0) := value;
    return ret;
  end pkg_toStdLogicVector;

  function pkg_toUnsigned (value : std_logic) return unsigned is
    variable ret : unsigned(0 downto 0);
  begin
    ret(0) := value;
    return ret;
  end pkg_toUnsigned;

  function pkg_toSigned (value : std_logic) return signed is
    variable ret : signed(0 downto 0);
  begin
    ret(0) := value;
    return ret;
  end pkg_toSigned;

  function pkg_stdLogicVector (lit : std_logic_vector) return std_logic_vector is
    variable ret : std_logic_vector(lit'length-1 downto 0);
  begin
    ret := lit;    return ret;
  end pkg_stdLogicVector;

  function pkg_unsigned (lit : unsigned) return unsigned is
    variable ret : unsigned(lit'length-1 downto 0);
  begin
    ret := lit;    return ret;
  end pkg_unsigned;

  function pkg_signed (lit : signed) return signed is
    variable ret : signed(lit'length-1 downto 0);
  begin
    ret := lit;    return ret;
  end pkg_signed;

  function pkg_resize (that : std_logic_vector; width : integer) return std_logic_vector is
  begin
    return std_logic_vector(resize(unsigned(that),width));
  end pkg_resize;


  function pkg_resize (that : unsigned; width : integer) return unsigned is
	  variable ret : unsigned(width-1 downto 0);
  begin
    if that'length = 0 then
       ret := (others => '0');
    else
       ret := resize(that,width);
    end if;
		return ret;
  end pkg_resize;
 
  function pkg_resize (that : signed; width : integer) return signed is
	  variable ret : signed(width-1 downto 0);
  begin
    if that'length = 0 then
       ret := (others => '0');
    elsif that'length >= width then
       ret := that(width-1 downto 0);
    else
       ret := resize(that,width);
    end if;
		return ret;
  end pkg_resize;
 end pkg_scala2hdl;


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.pkg_scala2hdl.all;
use work.all;
use work.pkg_enum.all;


entity FSM is
  port( 
    io_result : out std_logic;
    clk : in std_logic;
    reset : in std_logic 
  );
end FSM;

architecture arch of FSM is

  signal fsm_counter : unsigned(7 downto 0);
  signal fsm_stateReg : fsm_enumDefinition;
  signal fsm_stateNext : fsm_enumDefinition;
  signal zz_1 : std_logic;
  signal zz_2 : std_logic;
  signal zz_3 : std_logic;
  signal zz_4 : std_logic;
begin
  zz_1 <= pkg_toStdLogic(fsm_stateReg = pkg_enum.fsm_stateB);
  zz_2 <= pkg_toStdLogic(fsm_stateNext = pkg_enum.fsm_stateB);
  zz_3 <= pkg_toStdLogic(fsm_stateReg = pkg_enum.fsm_stateA);
  zz_4 <= pkg_toStdLogic(fsm_stateReg = pkg_enum.fsm_stateB);
  process(zz_1,zz_2)
  begin
    io_result <= pkg_toStdLogic(false);
    if (zz_1 and (not zz_2)) = '1' then
      io_result <= pkg_toStdLogic(true);
    end if;
  end process;

  process(fsm_counter,fsm_stateReg)
  begin
    fsm_stateNext <= fsm_stateReg;
    case fsm_stateReg is
      when pkg_enum.fsm_stateA =>
        fsm_stateNext <= pkg_enum.fsm_stateB;
      when pkg_enum.fsm_stateB =>
        if fsm_counter = pkg_unsigned("00000100") then
          fsm_stateNext <= pkg_enum.fsm_stateC;
        end if;
      when pkg_enum.fsm_stateC =>
        fsm_stateNext <= pkg_enum.fsm_stateA;
      when others =>
        fsm_stateNext <= pkg_enum.fsm_stateA;
    end case;
  end process;

  process(clk,reset)
  begin
    if reset = '1' then
      fsm_counter <= pkg_unsigned("00000000");
      fsm_stateReg <= pkg_enum.boot;
    elsif rising_edge(clk) then
      case fsm_stateReg is
        when pkg_enum.fsm_stateA =>
        when pkg_enum.fsm_stateB =>
          fsm_counter <= (fsm_counter + pkg_unsigned("00000001"));
        when others =>
      end case;
      if ((not zz_1) and zz_2) = '1' then
        fsm_counter <= pkg_unsigned("00000000");
      end if;
      fsm_stateReg <= fsm_stateNext;
    end if;
  end process;

end arch;

How to extend blackbox attribute support uint32_t parameter?

I try to implement a LUT5 as a blackbox with spinalhdl, but is not expect.

Thanks.

case class LUT5(INIT : Int) extends BlackBox {
val generic = new Generic {
val INIT = LUT5.this.INIT
}
val io = new Bundle {
val I0 = in Bool
val I1 = in Bool
val I2 = in Bool
val I3 = in Bool
val I4 = in Bool
val O = out Bool
}.setName("")
}

.......
val lut = LUT5(0x96696996) // xor

generated code:

LUT5 #(
.INIT(-1771476586)
) lUT5_1 (
.I0(zz_26),
.I1(zz_27),
.I2(zz_28),
.I3(zz_29),
.I4(zz_30),
.O(zz_14370)
);

Fixedpoint wrong generation for Verilog only

val a0  = in  Sfix( 0 exp,  -8 exp)
val b   = out Sfix(2 exp, -8 exp)
  b:= ((a0<<|1)+a0)<<|1

This can be correctly generated for vhdl only
in verilog you use operators '<<<' or '>>>' which are NOT adding any extra bits to LHS
In Vhdl functions pkg_shiftLeft are good way to use
but shifts >> or >>> or <<< or << are common mistake in verilog bit expansion

Use of generic signal names (_zz_...) when they don't need to be

IMO, one of the biggest issues with SpinalHDL is its tendency to use generic names for registers when there's really no reason to do so.

This really makes it a chore to analyze timing issues where they're no good reason for it to be that way.

For example, I have a small SOC for a hobby project that contains a VexRiscv:
https://github.com/tomverbeure/rv32soc/tree/vexriscv

When I run this design through Quartus, and run a timing analysis, I get a worst case timing path from register _zz_185[21] to the program memory.

Looking at the source code, _zz_185 is only used in the following two places:
https://github.com/tomverbeure/rv32soc/blob/2e194973097c6348a92b07cc519611327ed2b63c/vexriscv/VexRiscv_FullNoMmuNoCacheNoCsrNoDbg.v#L2081
and this:
https://github.com/tomverbeure/rv32soc/blob/2e194973097c6348a92b07cc519611327ed2b63c/vexriscv/VexRiscv_FullNoMmuNoCacheNoCsrNoDbg.v#L1062'

There is really no good reason to have this second assignment. The code should simply be:

    if((! decode_arbitration_isStuck))begin
      decode_INSTRUCTION <= _zz_73;
    end

(and, of course, _zz_73 should be fetch_INSTRUCTION as well.)

I totally understand an automated code generator will always result in cases where you end up with signal names that are auto-generated and meaningless. But the code generator should also go out of its way to only do this when it's strictly necessary, especially for clock registers, because those will show up in timing scripts, coverage reports etc.

Tom

Why the reset pin is there even when only the clock is needed ?

No matter how the register is defined, the generated Verilog code always has a reset,is this normal?

class Blink extends Component {
  val io = new Bundle {
    val led5 = out Bool
  }
  io.led5 := True

  val count = Reg(UInt(21 bits))
  count := count + 1

//  io.led5 := count.msb
}
module Blink (
      output  io_led5,
      input   clk,
      input   reset);
  reg [20:0] count;
  assign io_led5 = 1'b1;
  always @ (posedge clk) begin
    count <= (count + (21'b000000000000000000001));
  end

endmodule

Is it possible to generate such code ? thanks

module Blink (
      output  io_led5,
      input   clk);
  reg [20:0] count = 0; // defaults
  assign io_led5 = 1'b1;
  always @ (posedge clk) begin
    ……
  end

endmodule

Feature Proposal: allowing latches

Hi,
talking about latches (let's say today is Latch day ;) ), even if they are rarely used, they might be useful (for instance in describing clock gating cells).
I would propose to allow the intentional introduction of Latches, using tags, just as we do with combinatorial loops (with the "noCombinatorialLoopCheck" tag)
For instance, introducing a tag called "noLatchCheck" or something similar, we could define latches like follws:

  val d = Bool
  val e = Bool
  val l = Bool addTag(noLatchCheck)
  when (e) {
    l := d
  }

This would need to be translated in Verilog as:

  wire e;
  wire d;
  reg l;
  always @ (e or d)
  begin
    if(e)begin
      l <= d;
    end
  end

Let me point out that in Verilog (I don't know about VHDL) latches should be assigned using the non-blocking assignment ("<=") instead of the blocking assignment ("=").
Just a proposal, let me know what you think.
Thanks!

B(0) returns a Bit vector of 0 bits

Hi Dolu, Hi SpinalHDL development team.
Many thanks for the great job you have done (and you are doing). I started playing with SpinalHDL and it is amazing!!

I think I found a little issue. B(0) returns a Bits of 0 bits. I think it should return a Bits of 1 bit.
Found in master branch, SHA ID a6b3b9

Thanks and regards,

Cristian

Minimal support for assert, assume, cover

Right now, a SpinalHDL assert statement like this:

assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")

gets converted into something like this:

    if (!(! (((dBus_rsp_ready && memory_MEMORY_ENABLE) && memory_arbitration_isValid) && memory_arbitration_isStuck))) begin
      $display("ERROR DBusSimplePlugin doesn't allow memory stage stall when read happend");
    end

This is useful enough for simulation, but it's not for formal verification.

Today, Symbiyosys makes it possible to do formal verification with open source software.

Its default capabilities are limited and don't come close to the formal verification features of professional SystemVerilog tools, but they are sufficient to do formal proof of CPUs etc.

It'd be extremely useful to have support for these limited features in SpinalHDL.

All that's needed is the following:

  • A section that is surrounded by ifdef FORMAL ... endif
  • the ability to generate assert, assume, and cover statement
    These statement should be able to receive a Verilog expression just as is the case for, say, the expression of a port assignment
  • the ability to call some new functions such as $past, $rise, ...

The full manual of Symbiyosys is here.

An example is here:
https://github.com/YosysHQ/SymbiYosys/blob/2fef25f93dd1cb5137a08e71f507e3eee8100fb1/docs/examples/quickstart/demo.sv#L14-L18

Ideally, I think that the implementation of functionality should be split into 2 parts: one part that supports the insertion of the assert, assume etc statements. And one part that makes it possible to surround an arbitrary piece of code (for example, an Area or a Component) with arbitrary ifdef ... endif macros.

Tom

Unassigned, initialized register generates a Latch

When we have an initialized register declared but never assigned, a latch is generated (at least by the Verilog backend, I am not a VHDL expert...).
For instance

val fake_flop = Reg(Bool) init (False)

Generates the following Verilog code:

  reg  fake_flop;
  wire _1;
  assign _1 = 1'b0;
  always @ (posedge clk or posedge reset)
  begin
    if (reset) begin
      fake_flop <= _1;
    end else begin
    end
  end

Which describes a latch!
This causes the following 2 issues:

  1. If we declare a Reg, we want to se a Flop in our netlist, not a latch (at least this is what I would expect)
  2. Reset signal is connected to the "enable" input of the Latch: this is a misuse of the reset signal and might cause issues at backend

I see the following 3 ways to solve this issue (there might be more):

  1. Unassigned Registers give an error, even if they are initialized, just as it happens for Unassigned Uninitialized registers
  2. Unassigned Initialized Registers are converted into a constant
  3. Unassigned Initialized Registers generate Verilog code like the following:
  reg  fake_flop;
  wire _1;
  assign _1 = 1'b0;
  always @ (posedge clk or posedge reset)
  begin
    if (reset) begin
      fake_flop <= _1;
    end else begin
      fake_flop <= _1;
    end
  end

For completeness: I am working with the following git head: a6b3b9b

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.