signals in VHDL for .. generate scope - scope

A linting tool doesn't like the following block of code, because it thinks that the signals declared inside the for..generate scope have multiple drivers. Intuitively, I would expect that for each signal declaration, one instance of the signal would exist for each iteration of the loop.
Is the linter broken, or is it the VHDL language that is broken?
library IEEE;
use IEEE.std_logic_1164.all;
entity demo is
end demo;
architecture rtl of demo is
type i_arr_t is array(integer range <>) of integer;
signal results: i_arr_t(0 to 1);
signal dot : integer;
begin
g_gen : for ii in 0 to 1 generate
signal sig : integer;
begin
sig <= ii * 2;
results(ii) <= sig;
end generate;
dot <= results(0) + results(1);
end rtl;
Error message: Non-resolved signal 'sig' has multiple drivers

Related

A test bench for a phase counter using uvm

I am trying to create a uvm type test bench for a phase accumulator which is to be used in a DDS chain. Having this may be an overkill for a simple phase accumulator, but I am new to uvm/SystemVerilog so want to learn how to use the concepts. I have several questions.
My DUT:
module phase_acc #(
parameter PHASE_ACC_WIDTH = 16,
parameter TUNNING_WORD_WIDTH = 8
) (
input wire clk,
input wire reset,
input wire load,
input wire [TUNNING_WORD_WIDTH-1 : 0] tuning_word,
output reg [PHASE_ACC_WIDTH-1 : 0] phase,
output wire cycle_end,
output wire [1:0] phase_quadrant
);
assign phase_quadrant = phase[PHASE_ACC_WIDTH-1:PHASE_ACC_WIDTH-2];
assign cycle_end = (phase + tuning_word) > {PHASE_ACC_WIDTH{1'b1}};
always #(clk) begin
if (reset == 1) begin
phase <= 0;
end else begin
phase <= phase + tuning_word;
end
end
endmodule
Please note that this is not complete and planning to fill it after writing tests.
basic functionality is that the phase_acc counts up by tuning_word at a time. Just before it wraps around, it needs to assert cycle_end. Forget about phase_quadrant for now.
A new tuning_word can be loaded by asserting load.
I have created two classes to monitor signals. One for input stimulus (tuning_word and load) which gets triggered when ever load is one during a clock transition. The other is for phase_acc outputs which contain phase, cycle_end. Since these change at each clock transition, a new object of this type need to be created at each clock edge. Monitor uses two analysis ports to send stimulus packets and output packets to scoreboard.
My first question is, does this design make sense? Most uvm examples I saw have a behavior where after a stimulus is created, the DUT gives a single output which is then verified. (Say a RAM for example). In my case however, the DUT is free running.
If above design is correct, I have my second question.
My code for the monitor is:
class monitor extends uvm_monitor;
`uvm_component_utils(monitor)
function new(string name = "monitor", uvm_component parent = null);
super.new(name, parent);
endfunction
uvm_analysis_port #(acc_stimulus) mon_stimulus_analysis_port;
uvm_analysis_port #(acc_output) mon_output_analysis_port;
virtual reg_if vif;
semaphore sema4;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual acc_if)::get(this, "", "acc_if", vif))
`uvm_fatal("MON", "Could not get vif")
sema4 = new(1);
mon_stimulus_analysis_port = new("mon_stimulus_analysis_port", this);
mon_output_analysis_port = new("mon_output_analysis_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
forever begin
fork
begin
#(vif.clk);
// output
acc_output out = new;
out.phase = vif.phase;
out.cycle_end = vif.cycle_end;
out.phase_quadrant = cif.phase_quadrant;
`uvm_info(get_type_name(), $sformatf("Monitor found ouout %s", out.convert2str()),
UVM_LOW)
mon_output_analysis_port.write(out);
end
begin
#(vif.clk);
// stimulus
if (vif.ld) begin
acc_stimulus stimulus = new;
stimulus.tunning_word = vif.tuning_word;
stimulus.load = vif.ld;
`uvm_info(get_type_name(), $sformatf("Monitor found stimulus %s",
stimulus.convert2str()), UVM_LOW)
mon_stimulus_analysis_port.write(stimulus);
end
end
join
end
endtask
endclass
But when trying to compile this, I get an error for the line which says:
acc_output out = new;
I am not sure what I am doing wrong there. If I were to do this inside an if condition, for example:
begin
#(vif.clk);
if(vif.clk) begin
// output
acc_output out = new;
Then the error disappears.
I cannot understand what's wrong with the code.
You get the error because you declared the out variable in the middle of a begin/end block, after a statement:
begin
#(vif.clk); // This is a statement
// output
acc_output out = new; // This is a variable declaration
Inside a begin/end block, you must declare all variables before statements.
The error went away when you declared the variable in the if clause because it was the first line of code after the begin keyword. The fact that this was inside an if condition is irrelevant. The key was that you created a new block of code with the begin keyword.
This should also work:
begin
// output
acc_output out = new;
#(vif.clk);

Getting an error calling a task in verilog testbench

I've following tasks with different input vectors (that part is not written for simplicity) in my Verilog testbench
task input_set_1;
begin
end
endtask
task input_set_2;
begin
end
endtask
task input_set_3;
begin
end
endtask
task input_set_4;
begin
end
endtask
I'm trying to call only one of them during the testbench simulation using the below task
task input_calling;
integer i;
begin
i = $urandom_range(1, 4);
input_set_i;
end
endtask
initial begin
#3;
input_calling;
end
I'm expecting with each test run, any of the input_set_1, or input_set_2 or input_set_3 or input_set_4 will be called based on the random number i=1 to 4, however, I'm getting an error saying input_set_i is not defined. I suspect some string to int mismatch is preventing I to take randomized value in the input _set_i task.
You are trying to do something which is impossible in verilog (as well as in any non-scripting language). Name of the task is a compile-time element which must be known to the compiler at compilation time. i is a run-time, dynamic element. You cannot use run-time objects to modify compile-time objects.
So, your best bet is to use dynamic language features to make your program work, e.g. if statements. Here is an example:
module top;
task a;
$display("a");
endtask
task b;
$display("b");
endtask
initial begin
for (int k = 0; k < 4; k++) begin
automatic int i = $urandom_range(2,1);
if (i == 1)
a;
else if (i == 2)
b;
end
end
endmodule

VHDL - library doesn't work

I've create a new project on Quartus II with VHDL, but after I run it give me the errors shown below. Do you have any idea why?
Error (10481): VHDL Use Clause error at test_VHDL.vhd(5): design library "work" does not contain primary unit "std_arith"
Error (10800): VHDL error at test_VHDL.vhd(5): selected name in use clause is not an expanded name
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 2 errors, 1 warning
Error: Peak virtual memory: 1003 megabytes
Error: Processing ended: Sat Dec 5 19:50:39 2015
Error: Elapsed time: 00:00:13
Error: Total CPU time (on all processors): 00:00:38
Error (293001): Quartus II Full Compilation was unsuccessful. 4 errors, 1 warning
Here is my code:
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.std_arith.all; --extinde operatorul ” + “ la opera]ii \ntre semnale
--[i numere \ntregi
entity SUM is
port (a : in std_logic_vector(3 downto 0);
b : in std_logic;
ini,start,clk,a_disponibil,b_disponibil : in std_logic;
sum : out std_logic_vector(4 downto 0);
q : inout std_logic_vector(4 downto 0));
end SUM;
architecture arch_SUM of SUM is
signal load_a,load_b,reset,load_s : std_logic;
signal z : std_logic_vector(0 to 3);
type STARE is (S0,S1,S2,S3,S4); --st`rile automatului
signal S : STARE;
begin
--NUMARATOR
---------------------------------------------------------------
NUM : process(b)
begin
if rising_edge(b) then
if reset='1' then q<=(others=>'0');
elsif load_a='1' then
for i in 3 downto 0 loop --\ncarc` operandul a
q(i) <= a(i); --\n ultimii 3 bistabili
end loop; --ai num`r`torului
elsif load_b='1' then
q <= q+1; --adun` b la a
end if;
end if;
end process NUM;
--REGISTRU
--------------------------------------------------------------------
REG: process(clk)
begin
if rising_edge(clk) then
if reset='1' then sum<=(others=>'0');
elsif load_s='1' then
sum<=q;
end if;
end if;
end process REG;
--AUTOMAT
-----------------------------------------------------------------------------------
AUTOMAT : process(ini,clk)
begin
if INI='1' then s<=S0; --ini]ializeaz` automatul
elsif rising_edge(clk) then
case S is --descrie diagrama st`rilor
when S0 =>
if start='1' then S<=S1;
else S<=S0;
end if;
when S1 =>
if a_disponibil='1' then S<=S2;
else S<=S1;
end if;
when S2 =>
if b_disponibil='1' then S<=S3;
else S<=S2;
end if;
when S3 =>
if b_disponibil='0' then S<=S4;
else S<=S3;
end if;
when S4 => S<=S0;
end case;
end if;
end process AUTOMAT;
with S select
z<= "0000" when S0, --genereaz` ie[irea
"0010" when S1,
"1000" when S2,
"0100" when S3,
"0001" when others;
load_a <= z(0);
load_b <= z(1); --conexiuni interne
reset <= z(2);
load_s <= z(3);
end arch_SUM;
Have anyone idea why and how can solve it?
The statement use work.std_arith.all; introduces the sysnthesis compiler to look for a package std_arith in the same library as of the VHDL file. If you didn't specify one in the Quartus project settings, that it will be the default library. In this case, you have to provide your own implementation of the package and to add this file to the Quartus project as well.
If you are looking for the non-standard package from Synopsys, then you must change the line to use ieee.std_logic_arith.all;. But, this library does not define an operator + for the type std_logic_vector. EDIT The required operator is defined in the package std_logic_unsigned, if you want to treat your std_logic_vectors as unsigned numbers. The package is included with use ieee.std_logic_unsigned.all;. If you want signed arithmetic instead, then include use ieee.std_logic_signed.all;.
But, I recommend to use the standard IEEE library ieee.numeric_std instead, which defines arithmetic operators on the vector-types unsigned and signed.
For example, declare in the entity
sum : out unsigned(4 downto 0);
q : inout unsigned(4 downto 0);

How to use two switches in vhdl

I want to control the value of a variable using two switches. One for incrementing the value, whereas the other one for decrementing the value. How should i shange this code.
error says that the variable counting is unsynthesisable.
I have tried a lot but could not figure out what exactly the problem is.
ERROR:Xst:827 - line 34: Signal counting0 cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
entity counts is
port(
btn_up : in std_logic;
reset : IN STD_LOGIC;
btn_dn : in std_logic;
counted : out std_logic_vector(8 downto 0)
);
end entity counts;
architecture behaviour of counts is
signal counter : std_logic_vector(8 downto 0);
begin
btupprocess : process(btn_up,reset,counter)
variable counting : unsigned(8 downto 0);
begin
counting := unsigned(counter);
if(reset = '1') then
counting := (others => '0');
elsif (rising_edge(btn_up)) then
if(counting > 399) then
counting := counting - 1;
else
counting := counting + 1;
end if;
end if;
counter <= std_logic_vector(counting);
end process;
btndnprocess : process(btn_dn,counter)
variable counting : unsigned(8 downto 0);
begin
counting := unsigned(counter);
if (falling_edge(btn_dn)) then
if(counting < 200) then
counting := counting + 1;
else
counting := counting - 1;
end if;
end if;
counter <= std_logic_vector(counting);
end process;
counted <= counter;
end behaviour;
Although in some cases it is possible to drive a signal from two different processes, there are better approaches in this case.
A possible solution to your problem is:
add a clock input to your entity; you should probably use a synchronous design
rewrite your architecture to use three processes, with each process driving a single signal:
one process will debounce and detect a rising edge on btn_up; this process will generate the signal btn_up_rising_edge
one process will debounce and detect a rising edge on btn_dn; this process will generate the signal btn_dn_rising_edge
a third process will read btn_up_rising_edge and btn_dn_rising_edge, and increment or decrement the count as appropriate
in all three processes, your sensitiviy list should contain clock and reset only
You can find an example of an edge detector with a debouncer here: https://electronics.stackexchange.com/questions/32260/vhdl-debouncer-circuit

How to generate serial signal from string?

How do I send data represented by a binary string (e.g. "01011101000100111", length is variable) to an std_logic signal given either fixed delay or clock signal? I want this for a testbench so I'd want to be able to arbitrarily change the binary string with as little hassle as possible, so I'm thinking of using generate.
I humbly present a fixed-delay version (it is testbench code after all...). I've checked this and it works, but I'm more comfortable in verilog so this code may no be the nicest VHDL ever...
--
-- Clocking out bitstream
--
library ieee;
use ieee.std_logic_1164.all;
entity stackoverflow_strings is
end stackoverflow_strings;
-- this is testbench code, so we can use "wait"s inside a "for" loop.
architecture rtl of stackoverflow_strings is
signal my_output : std_ulogic;
begin
shift_data : process is
constant my_bits : std_logic_vector := B"100101010000100010101";
begin
my_output <= '0';
wait for 10 ns;
for i in my_bits'range loop
my_output <= my_bits(i);
wait for 10 ns;
end loop;
wait;
end process shift_data;
end rtl;
To add to Marty's fine answer:
To make it clocked, change the wait for 10 ns;s to wait until rising_edge(clk);

Resources