2
\$\begingroup\$

In VHDL I can make my modules arbitrary. Bus sizes flow from higher levels. That way I don't need to edit all my code every time I reuse a module.

Consider the following (incomplete) examples (This is a toy example to try to illustrate a point.)

In both examples:
The size of bus is implicit and late defined
The structure of displaystruct is made elsewhere.
The definition of decoder function is made elsewhere.

library IEEE;
use IEEE.std_logic_1164.all;
use work.displaylib.all;
-- In writing like this I can instance 'm' on any size bus without changing it.
entity m is
 port (
 clk : in std_logic;
 bus : in std_logic_vector;
 display : out displaystruct
 );
end entity;
architecture example of m is
begin
 if rising_edge(clk) then
 display <= decoder(bus);
 end if;
end architure;
library IEEE;
use IEEE.std_logic_1164.all;
use work.displaylib.all;
entity top is
end entity;
architecture example of top is
signal clk : std_logic;
signal bus : std_logic_vector(15 downto 0); --Late definition of bus
signal display : displaystruct;
begin
 controller : m port map (
 clk => clk,
 bus => bus,
 display => display);
end architecture;

I would like to do the same in SystemVerilog but I don't see how. You can't have arrays of undefined size (e.g. [])

`include "displaylib"
// Non working example as the array size of bus needs to be known
module m (
 input logic clk,
 input logic [] bus,
 output displaystruct display
)
 always @(posedge clk)
 begin
 display = decoder(bus);
 end
 
endmodule;
module top;
 logic clk;
 logic [15:0] bus; //Late definition of bus
 displaystruct display;
 
 controller m (
 .clk(clk),
 .bus(bus),
 .display(display)
 );
endmodule;
asked Oct 25, 2021 at 8:59
\$\endgroup\$
9
  • 2
    \$\begingroup\$ Interesting and I also don't know if it is possible, but: defining a parameter with the bus size at top module and passing it to the m module at the instantiation would not solve this cleanly? \$\endgroup\$ Commented Oct 25, 2021 at 9:45
  • \$\begingroup\$ By using a parameter you have a global, in any language that is not nice. I know I could use a typedef or use a module parameter (as I could a generic in VHDL) but that is not the question. This question is about late definition. A parameter would need the value either passed or updated in every instance. That creates a lot of work and error in a large design. Is there a more elegant synthesisable solution? \$\endgroup\$ Commented Oct 25, 2021 at 9:55
  • 2
    \$\begingroup\$ Not sure why you think parameters in HDL are 'global' and 'not nice'. That's debatable in software languages, but it has nothing special to do with HDLs because parameters are something simply elaborated by Synthesiser to numerics ahead of synthesis. Parameters are how ASIC/FPGA engineers build configurable designs, as in your requirements \$\endgroup\$ Commented Oct 25, 2021 at 13:26
  • 2
    \$\begingroup\$ @JasonM In both VHDL and Verilog, your displaystruct is never defined. It has to be defined somewhere. \$\endgroup\$ Commented Oct 25, 2021 at 17:55
  • 1
    \$\begingroup\$ @dave_59 In VHDL, we know that displaystruct is just a simple constained type (and not a record with unconstrained elements - although VHDL allows this now) because it was not sized in the signal declaration. It would be interesting to know if SV supports structures with unconstrained objects - and no constraints on the interface - I do this all the time in OSVVM VHDL verification components - handy feature. \$\endgroup\$ Commented Oct 26, 2021 at 5:42

1 Answer 1

1
\$\begingroup\$

You can do this in verilog by defining parameters in the module. You can override these parameters when you instantiate module inside top. Here is the example using your code:

module controller #(parameter BUS_WIDTH=16) //Here 16 is default value.
 ( input logic clk,
 input logic[BUS_WIDTH-1:0] bus,
 output displaystruct display
 )
 always @(posedge clk)
 begin
 display = decoder(bus);
 end
endmodule
module top;
 parameter FINAL_BUS_WIDTH = 32;
 
 logic clk;
 logic [BUS_WIDTH-1:0] bus; //Late definition of bus
 displaystruct display;
 
 controller m #(BUS_WIDTH = FINAL_BUS_WIDTH) // THis will create module with bus width 32
 .clk(clk),
 .bus(bus),
 .display(display)
 );
 controller m2 // THis will create module with bus width 16
 .clk(clk),
 .bus(bus),
 .display(display)
 );
 controller m3 #(BUS_WIDTH = 4) // THis will create module with bus width 4
 .clk(clk),
 .bus(bus),
 .display(display)
 );
 
 endmodule

In this example, I created BUS_WIDTH parameter in the module m whose default value is 16. This parameter can be overridden whenever you are instantiating the module m.

answered Nov 5, 2021 at 20:06
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.