Code Monkey home page Code Monkey logo

dfhdl's People

Contributors

scala-steward avatar soronpo avatar

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

Watchers

 avatar  avatar  avatar  avatar  avatar

dfhdl's Issues

Can't assign to indexed Bits(1) variable

Description

Trying to index and assign to a Bits(1) fails with the error below.

Example

import dfhdl.*

class Width0Issue(val width : Int <> CONST) extends RTDesign:
    val d = Bit <> IN
    val a = Bits(width) <> VAR
    a(0) := d // works only when width > 1
    // a := d  // works like this when width = 1

@main def main = 
     Width0Issue(1).compile
     Width0Issue(2).compile // works
DFiant HDL elaboration error!
Position: ~/Documents/DFHDL_examples/Issues.scala:6:5 - 6:9
Hierarchy: Width0Issue
Operation: `apply`
Message:   Unsigned value width must be positive, but found: 0

Clock and reset signals of submodules declared but not assigned in RTDesign

Example

val clkCfg1 = ClkCfg(ClkCfg.Edge.Rising)
val rstCfg1 = RstCfg(RstCfg.Mode.Sync, RstCfg.Active.High)
val rtcfg = RTDomainCfg(clkCfg1, rstCfg1)

class INV() extends RTDesign:
    val a = Bit <> IN
    val c = Bit <> VAR.REG init 0
    val b = Bit <> OUT
    c.din := a
    b := !a && c
    
class ClockRstConnection() extends RTDesign(rtcfg):
    val a = Bit <> IN
    val b = Bit <> OUT
    
    val inv0 = new INV()
    
    inv0.a <> a
    inv0.b <> b

@main def main = 
   ClockRstConnection().compile

Output

`default_nettype none
`timescale 1ns/1ps
`include "ClockRstConnection_defs.sv"

module ClockRstConnection(
  input wire logic clk,
  input wire logic rst,
  input wire logic a,
  output logic     b
);
  logic inv0_clk; // declared but never assigned
  logic inv0_rst;
  logic inv0_a;
  logic inv0_b;
  INV inv0(
    .clk /*<--*/ (inv0_clk),
    .rst /*<--*/ (inv0_rst),
    .a   /*<--*/ (inv0_a),
    .b   /*-->*/ (inv0_b)
  );
  assign inv0_a = a;
  assign b      = inv0_b;
endmodule

Verilog doesn't use arithmetic right shift for SInt

Description

>> is translated to >> in the case of SInt, but it should be >>>.

Example

import dfhdl._
class VerilogSRA() extends RTDesign:
    val a = SInt(10) <> IN
    val b = SInt(10) <> VAR
    
    b := a >> 1

@main def main = 
    VerilogSRA().compile

Output

module VerilogSRA(
  input wire logic signed [9:0] a
);
  logic signed [9:0] b;
  always @(*)
  begin
    b = a >> 1; \\ this is a logical right shift, which doesn't keep the sign bit
  end
endmodule

Clock and reset missing in generated files when top level is combinational

Descriptions

Clock and reset are missing in the generated code, when the top level class has both no REG and no explicit RTDomainCfg (that is, only compiler config is given). Basically, when the top level is combinational.

Example

class INV() extends RTDesign():
    val a = Bit <> IN
    val c = Bit <> VAR.REG init 0
    val b = Bit <> OUT
    c.din := a
    b := !a && c
    
class NoCfgClockRst() extends RTDesign(): // if RTDesign(cfg) it works fine
    val a = Bit <> IN
    val b = Bit <> OUT // with OUT.REG it works
    
    val inv0 = new INV()
    
    inv0.a <> a
    inv0.b <> b

given options.CompilerOptions.DefaultClkCfg = ClkCfg(ClkCfg.Edge.Rising)
given options.CompilerOptions.DefaultRstCfg = RstCfg(RstCfg.Mode.Sync, RstCfg.Active.Low)

@main def main = 
   NoCfgClockRst().compile

Output

`default_nettype none
`timescale 1ns/1ps
`include "NoCfgClockRst_defs.sv"

module INV(
  input wire logic a,
  output logic     b
);
  logic c;
  logic c_din;
  always @(*)
  begin
    c_din = c;
    c_din = a;
    b     = (!a) & c;
  end
endmodule
`default_nettype none
`timescale 1ns/1ps
`include "NoCfgClockRst_defs.sv"

module NoCfgClockRst(
  input wire logic a,
  output logic     b
);
  logic inv0_a;
  logic inv0_b;
  INV inv0(
    .a /*<--*/ (inv0_a),
    .b /*-->*/ (inv0_b)
  );
  assign inv0_a = a;
  assign b      = inv0_b;
endmodule

Missing conversion functions in VHDL pkg

Description

The functions to_bool and to_sl don't exist in the generated VHDL package.

Example

//> using scala 3.4.0
//> using dep io.github.dfianthdl::dfhdl::0.4.3+12-a64c002c-SNAPSHOT
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3+12-a64c002c-SNAPSHOT
//> using option -deprecation -language:implicitConversions

import dfhdl.*

class TypeConvertIssue() extends RTDesign:
    val a = Bit <> IN
    val b = Bit <> IN
    val c = UInt(8) <> IN
    val d = Bit <> OUT
    val e = Bit <> OUT
    
    d := 0
    if (c < 3 && b)
        d := 1

    e := 0
    if (b && c < 3)
        e := 1


 @main def main = 
    TypeConvertIssue().compile

Output

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

entity TypeConvertIssue is
port (
  a : in  std_logic;
  b : in  std_logic;
  c : in  unsigned(7 downto 0);
  d : out std_logic;
  e : out std_logic
);
end TypeConvertIssue;

architecture TypeConvertIssue_arch of TypeConvertIssue is
begin
  process (all)
  begin
    d <= '0';
    if (c < 8d"3") and to_bool(b) then d <= '1'; -- uses to_bool which does not exist
    end if;
    e <= '0';
    if b and to_sl(c < 8d"3") then e <= '1'; -- uses to_sl which does not exist
    end if;
  end process;
end TypeConvertIssue_arch;

to_slv function missing for std_logic

Description

Generated VHDL uses the function to_slv to convert b(0), but the function does not exist for std_logic.

The following function is needed

-- in package header
function to_slv(A : std_logic) return std_logic_vector;

-- in package body
function to_slv(A : std_logic) return std_logic_vector is
begin
  if A = '1' then 
    return "1";
  else
    return "0";
  end if;
end;

Example

class StdLogicConvIssue() extends RTDesign:
    val a = Bits(10) <> IN
    val e = Bits(10) <> OUT

    e := (a(0), a(3), b"0", false.bit, b"000000")

Output

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

entity StdLogicConvIssue is
port (
  a : in  std_logic_vector(9 downto 0);
  e : out std_logic_vector(9 downto 0)
);
end StdLogicConvIssue;

architecture StdLogicConvIssue_arch of StdLogicConvIssue is
begin
  process (all)
  begin
    e <= to_slv(a(0)) & to_slv(a(3)) & "0" & "0" & 6x"00"; -- problem here
  end process;
end StdLogicConvIssue_arch;

Double struct declaration for VHDL

Description

Structs that are used in the port declaration are declared in the package, whereas structs used internally are declared in the architecture, which leads to double struct declaration.

Example

case class InStruct (
    a : Bit <> VAL,
    b : Bit <> VAL
) extends Struct

class DoubleStructDecl() extends RTDesign():
    val sin = InStruct <> IN
    val svar = InStruct <> VAR
    svar := sin

given options.CompilerOptions.Backend = backends.vhdl.v2008

@main def main = 
   DoubleStructDecl().compile

Output

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

entity DoubleStructDecl is
port (
  clk : in std_logic;
  rst : in std_logic;
  sin : in t_struct_InStruct -- declared in the package
);
end DoubleStructDecl;

architecture DoubleStructDecl_arch of DoubleStructDecl is
  type t_struct_InStruct is record -- redeclared here
    a : std_logic;
    b : std_logic;
  end record;
  signal svar : t_struct_InStruct;
begin
  process (all)
  begin
    svar <= sin;
  end process;
end DoubleStructDecl_arch;

Head of empty list error for if

Description

Same error message as #116 and seems related to if statements again. The error occurs for both VHDL and Verilog.

Example

import dfhdl.*

class DictControl(
    val fetch_count : Int <> CONST,  // set to 2
    val dict_entry_size : Int = 20
) extends RTDesign:
    val dict_in = Bits(fetch_count * dict_entry_size) <> IN 
    
    val matching = Bits(fetch_count) <> VAR
    val addr_r = Bits(12) <> VAR.REG init all(0)
    val idx_r = Bits(12) <> VAR.REG init all(0)
    val sym_r = Bits(8) <> VAR.REG init all(0)
    val entry_count = UInt(12) <> VAR.REG init 0
    
    entry_count.din := 0
    sym_r.din := b"8'0"
    idx_r.din := b"12'0"
    addr_r.din := b"12'0"
    
    for (i <- 0 until fetch_count.toScalaInt)
        if ((dict_in(dict_entry_size * (i+1) - 1, dict_entry_size * i) == (idx_r, sym_r)) && (addr_r + i < entry_count - 1))
            matching(i) := 1

@main def main = 
   DictControl(fetch_count = 2).compile

Output

Exception in thread "main" java.util.NoSuchElementException: head of empty list
        at scala.collection.immutable.Nil$.head(List.scala:662)
        at scala.collection.immutable.Nil$.head(List.scala:661)
        at dfhdl.compiler.ir.DB.OMLGen(DB.scala:137)
        at dfhdl.compiler.ir.DB.blockMemberList$lzyINIT1(DB.scala:221)
        at dfhdl.compiler.ir.DB.blockMemberList(DB.scala:221)
        at dfhdl.compiler.stages.UniqueNames.transform(UniqueNames.scala:72)
        at dfhdl.compiler.stages.StageRunner.runSingleStage(StageRunner.scala:22)
        at dfhdl.compiler.stages.StageRunner.dfhdl$compiler$stages$StageRunner$$run(StageRunner.scala:43)
        at dfhdl.compiler.stages.StageRunner$.run(StageRunner.scala:55)
        at dfhdl.backends$vhdl.printer(backends.scala:27)
        at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
        at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
        at dfhdl.backends$vhdl.compile(backends.scala:23)
        at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
        at dfhdl.ops$package$.compile(ops.scala:10)
        at project$package$.main(project.scala:39)
        at main.main(project.scala:27)

Array type is not generated for vectors (VHDL)

Description

The generated code of the entity uses the types t_array_elem0 / t_array_elem1/t_array_elem2, which do not exist in the associated package.

I am also wondering what multidimensional arrays would look like.
Either
type <name> is array (natural range <>, natural range <>, ...) of <element_type>
and indexed as e.g. arr(0, 0, ...)
or
type <name1> is array (natural range <>) of <element_type>
type <name2> is array (natural range <>) of <name1>
and indexed as e.g. arr(0)(0)...

Example

//> using scala 3.4.0
//> using dep io.github.dfianthdl::dfhdl::0.4.6
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.6
//> using option -deprecation -language:implicitConversions

import dfhdl.*

class ArrayIssue() extends RTDesign:
    val a = Bit <> IN
    val b = Bit X 6 <> VAR
    val c = Bit X 5 X 4 <> VAR
    val d = Bits(4) X 3 X 2 <> VAR
    
    b(0) := a
    c(0)(0) := a
    d(0)(0)(0) := a

given options.CompilerOptions.PrintGenFiles = true
given options.CompilerOptions.Backend = backends.vhdl

@main def main = 
   ArrayIssue().compile

Output

If c and d are indexed as in the VHDL code it would require the latter variant of multidimensional arrays above.

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

entity ArrayIssue is
port (
  a : in std_logic
);
end ArrayIssue;

architecture ArrayIssue_arch of ArrayIssue is
  signal b : t_array_elem0(0 to 6 - 1);
  signal c : t_array_elem1(0 to 4 - 1);
  signal d : t_array_elem2(0 to 2 - 1);
begin
  process (all)
  begin
    b(0) <= a;
    c(0)(0) <= a;
    d(0)(0)(0) <= a; 
  end process;
end ArrayIssue_arch;

Incorrect conversion of signed SRA and std_logic_vector SRL for VHDL

Description

Shifts are incorrectly converted to VHDL incorrectly in some cases. For a bitvector right shift sla is used instead of srl and for signed right shift the generated signed_sra function converts the signed value to unsigned, which leads to incorrect behavior for negative numbers. Shifts with unsigned (UInt) seem correct.

Example

//> using scala 3.4.0
//> using dep io.github.dfianthdl::dfhdl::0.4.3+12-a64c002c-SNAPSHOT
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3+12-a64c002c-SNAPSHOT
//> using option -deprecation -language:implicitConversions

import dfhdl.*

class ShiftIssue() extends RTDesign:  
    val bitvec = Bits(10) <> VAR
    val bitvec2 = Bits(10) <> OUT
    val bitvec3 = Bits(10) <> VAR
    
    val signed1 = SInt(10) <> VAR
    val signed2 = SInt(10) <> OUT
    val signed3 = SInt(10) <> OUT
    
    val unsigned1 = UInt(10) <> VAR
    val unsigned2 = UInt(10) <> OUT
    val unsigned3 = UInt(10) <> OUT

    bitvec2 := bitvec >> 1 // not ok, uses sla instead of srl
    bitvec3 := bitvec << 1 // ok
    
    signed2 := signed1 >> 1 // not ok, converts value to unsigned before applying sra
    signed3 := signed1 << 1 // ok

    unsigned2 := unsigned1 >> 1
    unsigned3 := unsigned1 << 1 

given options.CompilerOptions.PrintGenFiles = true
given options.CompilerOptions.Backend = backends.vhdl

 @main def main = 
    ShiftIssue().compile

Output

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

entity ShiftIssue is
port (
  bitvec2   : out std_logic_vector(9 downto 0);
  signed2   : out signed(9 downto 0);
  signed3   : out signed(9 downto 0);
  unsigned2 : out unsigned(9 downto 0);
  unsigned3 : out unsigned(9 downto 0)
);
end ShiftIssue;

architecture ShiftIssue_arch of ShiftIssue is
  signal bitvec    : std_logic_vector(9 downto 0);
  signal bitvec3   : std_logic_vector(9 downto 0);
  signal signed1   : signed(9 downto 0);
  signal unsigned1 : unsigned(9 downto 0);
begin
  process (all)
  begin
    bitvec2   <= slv_srl(bitvec, 4d"1");
    bitvec3   <= slv_sll(bitvec, 4d"1");
    signed2   <= signed_sra(signed1, 4d"1");
    signed3   <= signed1 sla 1;
    unsigned2 <= unsigned1 srl 1;
    unsigned3 <= unsigned1 sll 1;
  end process;
end ShiftIssue_arch;
-- only relevant parts 
function slv_sll(slv : std_logic_vector; num_shifts : unsigned) return std_logic_vector is
begin
    return to_slv(unsigned(slv) sll to_integer(num_shifts));
end;
function slv_srl(slv : std_logic_vector; num_shifts : unsigned) return std_logic_vector is
begin
    return to_slv(unsigned(slv) sla to_integer(num_shifts)); -- uses sla
end;
function signed_sra(A : signed; num_shifts : unsigned) return signed is
begin
    return signed(unsigned(A) sra to_integer(num_shifts)); -- converted to unsigned
end;
end package body ShiftIssue_pkg;

Error in VHDL code gen when vectors are part of struct

Example

import dfhdl._

case class EmbeddedArray (
    a : Bits[8]X(3) <> VAL
) extends Struct
    
class StructArrayIssue() extends RTDesign:
    val a = Bit <> IN
    val e = EmbeddedArray <> VAR
    e.a(0)(0) := a

given options.CompilerOptions.Backend = backends.vhdl.v2008

@main def main = 
   StructArrayIssue().compile

Output

Exception in thread "main" java.lang.IllegalArgumentException: Unsupported member for this RTPrinter.
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.unsupported(VHDLPrinter.scala:17)
        at dfhdl.compiler.stages.vhdl.VHDLValPrinter.csBitsToType(VHDLValPrinter.scala:116)
        at dfhdl.compiler.stages.vhdl.VHDLValPrinter.csBitsToType$(VHDLValPrinter.scala:8)
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.csBitsToType(VHDLPrinter.scala:8)
        at dfhdl.compiler.stages.vhdl.VHDLTypePrinter.$anonfun$5(VHDLTypePrinter.scala:156)
        at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100)
        at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87)
        at scala.collection.immutable.ListMap.map(ListMap.scala:43)
        at dfhdl.compiler.stages.vhdl.VHDLTypePrinter.csDFStructConvFuncsBody(VHDLTypePrinter.scala:156)
        at dfhdl.compiler.stages.vhdl.VHDLTypePrinter.csDFStructConvFuncsBody$(VHDLTypePrinter.scala:10)
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.csDFStructConvFuncsBody(VHDLPrinter.scala:8)
        at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter$$anon$3.applyOrElse(VHDLOwnerPrinter.scala:58)
        at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter$$anon$3.applyOrElse(VHDLOwnerPrinter.scala:58)
        at scala.collection.Iterator$$anon$7.hasNext(Iterator.scala:525)
        at scala.collection.IterableOnceOps.addString(IterableOnce.scala:1245)
        at scala.collection.IterableOnceOps.addString$(IterableOnce.scala:1241)
        at scala.collection.AbstractIterable.addString(Iterable.scala:933)
        at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1191)
        at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1189)
        at scala.collection.AbstractIterable.mkString(Iterable.scala:933)
        at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1204)
        at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1204)
        at scala.collection.AbstractIterable.mkString(Iterable.scala:933)
        at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csArchitectureDcl(VHDLOwnerPrinter.scala:59)
        at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csArchitectureDcl$(VHDLOwnerPrinter.scala:10)
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.csArchitectureDcl(VHDLPrinter.scala:8)
        at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csDFDesignBlockDcl(VHDLOwnerPrinter.scala:89)
        at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csDFDesignBlockDcl$(VHDLOwnerPrinter.scala:10)
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.csDFDesignBlockDcl(VHDLPrinter.scala:8)
        at dfhdl.compiler.printing.Printer.csFile(Printer.scala:150)
        at dfhdl.compiler.printing.Printer.csFile$(Printer.scala:19)
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.csFile(VHDLPrinter.scala:8)
        at dfhdl.compiler.printing.Printer.$anonfun$1(Printer.scala:170)
        at scala.collection.immutable.List.map(List.scala:246)
        at dfhdl.compiler.printing.Printer.printedDB(Printer.scala:172)
        at dfhdl.compiler.printing.Printer.printedDB$(Printer.scala:19)
        at dfhdl.compiler.stages.vhdl.VHDLPrinter.printedDB(VHDLPrinter.scala:8)
        at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
        at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
        at dfhdl.backends$vhdl.compile(backends.scala:23)
        at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
        at dfhdl.ops$package$.compile(ops.scala:10)
        at project$package$.main(project.scala:51)
        at main.main(project.scala:27)

VHDL array indexing requires to_integer function

Description

Arrays require integers for indexing, but the generated VHDL uses unsigned (for non constant values). The function to_integer() should be used.

Example

import dfhdl._

class IntegerIndexingIssue() extends RTDesign:
    val a = Bits(4) <> IN
    val b = Bits(12) X 16 <> VAR.REG init all(all(0))
    val c = Bits(12) <> OUT
    
    c := b(a)

given options.CompilerOptions.PrintGenFiles = true
given options.CompilerOptions.Backend = backends.vhdl.v2008

@main def main = 
   IntegerIndexingIssue().compile

Output

architecture IntegerIndexingIssue_arch of IntegerIndexingIssue is
  type t_vecX1_std_logic_vector is array (natural range <>) of std_logic_vector;
  signal b     : t_vecX1_std_logic_vector(0 to 16 - 1)(11 downto 0);
  signal b_din : t_vecX1_std_logic_vector(0 to 16 - 1)(11 downto 0);
begin
  process (all)
  begin
    b_din <= b;
    c     <= b(unsigned(a)); -- to_integer(unsigned(a));
  end process;
  process (clk)
  begin
    if rising_edge(clk) then
      if rst = '1' then b <= (0 to 16-1 => x"000");
      else b <= b_din;
      end if;
    end if;
  end process;
end IntegerIndexingIssue_arch;

Compile error when using struct fields in nested if

Description

Trying to use a field of a struct in a level other than the outermost one of a nested if yields an error. It works fine otherwise and also works when assigning the field to a variable and using that variable in an inner level.

Example

//> using scala 3.4.0
//> using lib io.github.dfianthdl::dfhdl::0.4.3
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3
//> using option -deprecation -language:implicitConversions

import dfhdl.* //import all the DFHDL goodness

case class Test (
  a : Bit <> VAL,
  b : Bit <> VAL
) extends Struct


class GlobCounter (val width: Int <> CONST) extends RTDesign:
  val req = Bit <> IN
  val req2 = Bit <> IN
  val t = Test <> IN
  val t_b = Bit <> VAR
  t_b := t.b
  val t_int = Test <> VAR 
  t_int := t
  
  val cnt = UInt(width) <> OUT.REG init 0
   
  // doesn't work
  if (t.a) {
    if (t.b) { 
        cnt.din := cnt + 1
    }
  }
  
  // doesn't work
//   if (req) {
//     if (t.b) { 
//         cnt.din := cnt + 1
//     }
//   }

  // no if nesting, works
//   if (t.a && t.b) {
//     cnt.din := cnt + 1
//   }
  
  // works
//   if (t.a) {
//     if (t_b) { 
//         cnt.din := cnt + 1
//     }
//   }

  // doesn't work
//   if (t_int.a) {
//     if (t_int.b) { 
//         cnt.din := cnt + 1
//     }
//   }
  
  // works
//   if (req) {
//     if (req2) {
//       cnt.din := cnt + 1
//     }
//   }

////////////////////////////////////////////////////////////////////////////////////////////////
// DFHDL Compiler Options:                                                                    //
////////////////////////////////////////////////////////////////////////////////////////////////
// Enables printing the generated chosen backend code:
given options.CompilerOptions.PrintGenFiles = true
// Uncomment to select vhdl compilation (default is verilog):
// given options.CompilerOptions.Backend = backends.vhdl
// Uncomment to enable printing design code before compilation (after elaboration):
// given options.CompilerOptions.PrintDesignCodeBefore = true
// Uncomment to enable printing design code after compilation:
// given options.CompilerOptions.PrintDesignCodeAfter = true
// Uncomment to set different clock and reset configurations:
// given options.CompilerOptions.DefaultClkCfg = ClkCfg(ClkCfg.Edge.Rising)
// given options.CompilerOptions.DefaultRstCfg = RstCfg(RstCfg.Mode.Async, RstCfg.Active.Low)
////////////////////////////////////////////////////////////////////////////////////////////////

//The entry point to your compilation program starts here
@main def main = GlobCounter(64).compile

Output

When run with scala-cli this is the output

[warn] ./GlobCounter.scala:2:11
[warn] Using 'lib' is deprecated, use 'dep' instead
[warn] //> using lib io.github.dfianthdl::dfhdl::0.4.3
[warn]           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compiling project (Scala 3.4.0, JVM (17))
Compiled project (Scala 3.4.0, JVM (17))
Exception in thread "main" java.util.NoSuchElementException: head of empty list
        at scala.collection.immutable.Nil$.head(List.scala:662)
        at scala.collection.immutable.Nil$.head(List.scala:661)
        at dfhdl.compiler.ir.DB.OMLGen(DB.scala:137)
        at dfhdl.compiler.ir.DB.ownerMemberList$lzyINIT1(DB.scala:165)
        at dfhdl.compiler.ir.DB.ownerMemberList(DB.scala:165)
        at dfhdl.compiler.ir.DB.ownerMemberTable$lzyINIT1(DB.scala:190)
        at dfhdl.compiler.ir.DB.ownerMemberTable(DB.scala:190)
        at dfhdl.compiler.ir.DB.getMembersOf(DB.scala:181)
        at dfhdl.compiler.analysis.DFOwnerAnalysis$package$.members(DFOwnerAnalysis.scala:8)
        at dfhdl.compiler.stages.VHDLProcToVerilog$.$anonfun$1(VHDLProcToVerilog.scala:33)
        at scala.collection.immutable.List.flatMap(List.scala:293)
        at dfhdl.compiler.stages.VHDLProcToVerilog$.transform(VHDLProcToVerilog.scala:82)
        at dfhdl.compiler.stages.StageRunner.runSingleStage(StageRunner.scala:22)
        at dfhdl.compiler.stages.StageRunner.dfhdl$compiler$stages$StageRunner$$run(StageRunner.scala:43)
        at dfhdl.compiler.stages.StageRunner$.run(StageRunner.scala:55)
        at dfhdl.backends$verilog.printer(backends.scala:15)
        at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
        at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
        at dfhdl.backends$verilog.compile(backends.scala:11)
        at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
        at dfhdl.ops$package$.compile(ops.scala:10)
        at GlobCounter$package$.main(GlobCounter.scala:82)
        at main.main(GlobCounter.scala:82)

Missing functions in std_logic_vector to struct conversion

Description

In std_logic_vector to struct conversion functions, bitWidth(A) is used, where A is the input and a std_logic_vector, but the function doesn't exist. The function to_sl() is used on a sliced std_logic_vector, but only exists for bools. This happens for Bit /std_logic in a struct. Either a function like to_sl(A : std_logic_vector(0 downto 0)) (1) is needed or alternatively A(lo) is assigned instead of to_sl(A(hi downto lo)).

Example

import dfhdl._

case class Atest (
    a : Bits[10] <> VAL,
    b : UInt[10] <> VAL,
    c : SInt[10] <> VAL,
    d : Bit <> VAL
) extends Struct;

class StructConvIssue() extends RTDesign:
    val a = Bits(10) <> IN
    
    val Astruct = Atest <> VAR
    Astruct.a := a
    Astruct.b := a
    Astruct.c := a.sint

@main def main = 
   StructConvIssue().compile

Output

-- pkg not shown
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.StructConvIssue_pkg.all;

entity StructConvIssue is
port (
  a : in std_logic_vector(9 downto 0)
);
end StructConvIssue;

architecture StructConvIssue_arch of StructConvIssue is
  type t_struct_Atest is record
    a : std_logic_vector(9 downto 0);
    b : unsigned(9 downto 0);
    c : signed(9 downto 0);
    d : std_logic;
  end record;
  function bitWidth(A : t_struct_Atest) return integer is
    variable len : integer;
  begin
    len       := 0;
    len       := len + A.a'length;
    len       := len + A.b'length;
    len       := len + A.c'length;
    len       := len + 1;
    return len;
  end;
  function to_slv(A : t_struct_Atest) return std_logic_vector is
    variable hi  : integer;
    variable lo  : integer;
    variable ret : std_logic_vector(bitWidth(A) - 1 downto 0);
  begin
    lo        := bitWidth(A);
    hi        := lo - 1; lo := hi - A.a'length + 1; ret(hi downto lo) := A.a;
    hi        := lo - 1; lo := hi - A.b'length + 1; ret(hi downto lo) := to_slv(A.b);
    hi        := lo - 1; lo := hi - A.c'length + 1; ret(hi downto lo) := to_slv(A.c);
    hi        := lo - 1; lo := hi - 1 + 1; ret(hi downto lo) := to_slv(A.d);
    return ret;
  end;
  function to_t_struct_Atest(A : std_logic_vector) return t_struct_Atest is
    variable hi  : integer;
    variable lo  : integer;
    variable ret : t_struct_Atest;
  begin
    lo        := bitWidth(A); -- A is a std_logic_vector, should be 'length instead?
    hi        := lo - 1; lo := hi - ret.a'length + 1; ret.a := A(hi downto lo);
    hi        := lo - 1; lo := hi - ret.b'length + 1; ret.b := unsigned(A(hi downto lo));
    hi        := lo - 1; lo := hi - ret.c'length + 1; ret.c := signed(A(hi downto lo));
    hi        := lo - 1; lo := hi - 1 + 1; ret.d := to_sl(A(hi downto lo)); -- to_sl used on a sliced std_logic_vector which has width 1
    return ret;
  end;
  signal Astruct : t_struct_Atest;
begin
  process (all)
  begin
    Astruct.a <= a;
    Astruct.b <= unsigned(a);
    Astruct.c <= signed(a);
  end process;
end StructConvIssue_arch;

(1)

-- pkg header
function to_sl(A : std_logic_vector(0 downto 0)) return std_logic;

-- pkg body
function to_sl(A : std_logic_vector(0 downto 0)) return std_logic
  is
  begin
    if (A = "1") then
      return '1';
    else
      return '0';
    end if;
end;

prev/prev(1) is not correctly assigned to VARs

Description

Assigning .prev / .prev(1) to an OUT gives the expected result, but assigning it to a VAR doesn't. In the below example, the Verilog code has a being assigned to c directly instead of a_reg1. For higher orders, it works as expected, as shown by e.

Example

import dfhdl.*

class FirstDF() extends DFDesign:
    val a = Bit <> IN init 0
    val c = Bit <> VAR 
    val e = Bit <> VAR
    c := a.prev(1)
    e := a.prev(2)
    
    val d = Bit <> OUT init 0
    d := a.prev

@main def main = 
    FirstDF().compile

Output

module FirstDF(
  input wire logic clk,
  input wire logic rst,
  input wire logic a,
  output logic     d
);
  logic c;
  logic e;
  logic a_reg1;
  logic a_reg2;
  always @(*)
  begin
    e        = a_reg2;
    d        = a_reg1;
  end
  always @(posedge clk)
  begin
    if (rst == 1'b1) begin
      a_reg1 <= 1'b0;
      a_reg2 <= 1'b0;
      c      <= 1'b0;
    end
    else begin
      a_reg1 <= a;
      a_reg2 <= a_reg1;
      c      <= a;
    end
  end
endmodule

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.