Forum Discussion
problem (?) using shared variables
Hi,
I need your kind opinion. Please, anyone explain me why the following code is not running. VHDL code (sel-explainable)
------------------------------------------------------
entity counter_with_sharedvar is
port (clk: in bit;
digit1, digit2: out integer range 0 to 9);
end entity;
------------------------------------------------------
architecture counter of counter_with_sharedvar is
shared variable temp1, temp2: integer range 0 to 9;
begin
----------------------------------
proc1: process (clk)
begin
if (clk'EVENT and clk='1') then
if (temp1=9) then
temp1 := 0;
else
temp1 := temp1 + 1;
end if;
end if;
end process proc1;
----------------------------------
proc2: process (clk)
begin
if (clk'EVENT and clk='1') then
if (temp1=9) then
if (temp2=9) then
temp2 := 0;
else
temp2 := temp2 + 1;
end if;
end if;
end if;
end process proc2;
----------------------------------
digit1 <= temp1;
digit2 <= temp2;
end architecture;
VHDL testbench code
entity tb_cct is
end entity tb_cct;
architecture arch of tb_cct is
constant T: time := 20 ns;
signal t_clk: bit;
signal t_d1: integer range 0 to 9;
signal t_d2: integer range 0 to 9;
begin
uut: entity work.counter_with_sharedvar(counter)
port map(clk => t_clk, digit1 => t_d1, digit2 => t_d2);
process
begin
t_clk <= '0';
wait for T/2;
t_clk <= '1';
wait for T/2;
end process;
end arch;
simulation result (50 MHz oscilator) https://www.alteraforum.com/forum/attachment.php?attachmentid=7548 Any ideas? Regards Jaraqui26 Replies
- Altera_Forum
Honored Contributor
Well I just tried modesim and your first code works as temp1 and temp2 increment but digit1 and digit2 stay 0
- Altera_Forum
Honored Contributor
--- Quote Start --- Well I just tried modesim and your first code works as temp1 and temp2 increment --- Quote End --- But the outputs digit1 and digit 2 remain at the the initial values of temp1 and temp2 (0) - Altera_Forum
Honored Contributor
true and I get warning saying shared variables must be of type protected. God knows how to protect them.
- Altera_Forum
Honored Contributor
I know - and its only for simulation. A protected type is a bit like a class in C++. They contain member variables, functions and procedures and can be extremly useful for behavioural modelling. In VHDL 2002, they made it a LRM rule that shared variables MUST be protected types, but as this would break old VHDL '93 code, and so by default it only throws a warning (you can make it stricter though).
so, as an example:
And then wrap an entity around this shared variable to make it behave like a DDR chip, but it will only use system ram as individual rows are accesses, so you dont need to use a massive amount of ram during simulation to model the memory, and it runs much faster.type DDR_model_t is protected procedure write_data(addr : integer; data : std_logic_vector); impure function read_data(addr: integer) return std_logic_vector; end proteted DDR_Model_t; type ddr_model_t is protected body type mem_row_t is array(0 to 1023) of std_logic_vector(31 downto 0); type mem_row_ptr_t is access mem_row_t; type mem_bank_t is array(0 to 1023) of mem_row_ptr_t; type mem_bank_ptr_t is access mem_bank_t; type mem_t is array(0 to 7) of mem_bank_ptr_t; variable mem : mem_t; procedure write_data(addr: integer; data : std_logic_vector) is variable bank, row, col : integer; begin bank = addr rem 8; row = (addr/8)/1024; col = (addr rem 1024); if mem(bank) = null then mem(bank) := new mem_bank_t; end if; if mem(bank)(row) = null then mem(bank)(row) := new mem_row_t; end if; mem(bank)(row)(col) := data; end procedure write_data; impure function read_data(addr: integer) return std_logic_vector is variable bank, row, col : integer; CONSTANT ALL_U : std_logic_vector(31 downto 0) := (others => 'U'); begin bank = addr rem 8; row = (addr/8)/1024; col = (addr rem 1024); if mem(bank) = null or mem(bank)(row) = null then return ALL_U; else return mem(bank)(row)(col); end if; end function read_data; end protected ddr_model_t; shared variable ddr_model : ddr_model_t; --to use it: ddr_model.write_data(a); some_var := ddr_model.read_data(b); - Altera_Forum
Honored Contributor
They also can be useful for handling event queues (like a load of packets arriving on a PCIe bus) - as you can have pointers in VHDL you can make linked lists of an infinite size during simulation
- Altera_Forum
Honored Contributor
Tricky,
Without your help, without the help from another collegue from another forum, without the collaboration of another collegue from here (variable initialization), it couldn´t be possible for me to exit from step zero to step one. And I thank you for this. I thank also all the people here for the "temperature" in this forum. The objectivity of the problem stay fixed, withou any extreme "ego" unecessary discussions. Of course the "nerd-Big-Bang-theory-discussion" must exist because is part of us. This kind of discussion is obviously different from the former cited. I think all we enter in this type discussion at some moment, even when the impulse is involutary. Two paragraphs of "speech" to do an invitment. I like posts such this because the code is small and easly reproductible and we talking about only one specific problem. Someone who googles the problem can find here the solution. To finish gracefully, to eliminate the last "evil", it is necessary to generate a 1 Hz clock without logic, as Tricky and other people already did recommend. Can someone who is interested (and knows how to do it) modificate this last version with the so called clock enabling version (plus initializing temp1/temp2). Is it dificult? I ask this because I don´t know how to do at this time (I will look for good books or expect someone recommend one...). Let me know if someone can do! Regards Jaraqui - Altera_Forum
Honored Contributor
--- Quote Start --- true and I get warning saying shared variables must be of type protected. God knows how to protect them. --- Quote End --- I saw something at ASHENDEN(2008, p. 585), but I assure to you: I don´t have the appropriate patiente to follow that book. ASHENDEN, Peter J. the designer's guide to vhdl. 3rd ed. Burlington: Morgan Kaufmann Series, 2008. - Altera_Forum
Honored Contributor
--- Quote Start --- Can someone who is interested (and knows how to do it) modificate this last version with the so called clock enabling version (plus initializing temp1/temp2). Is it dificult? I ask this because I don´t know how to do at this time (I will look for good books or expect someone recommend one...). --- Quote End --- Ill give you the outline - its very similar to what you're doing:process(clk) begin if rising_edge(clk) then cnt <= cnt + 1; if cnt = N then -- this will give you an enable rate of clk/N clk_en <= '1'; else clk_en <= '0'; end if; if clk_en = '1' then --do something once every N clocks end if; end process; - Altera_Forum
Honored Contributor
--- Quote Start --- Ill give you the outline - its very similar to what you're doing:
--- Quote End --- Forgetting momentarily the shared variables stuff and concentrating only in a simple clock generator based on this piece of code you provided, I developed the following code:process(clk) begin if rising_edge(clk) then cnt <= cnt + 1; if cnt = N then -- this will give you an enable rate of clk/N clk_en <= '1'; else clk_en <= '0'; end if; if clk_en = '1' then --do something once every N clocks end if; end process;
Implementing it to blink a simple led receiving clk at expected 1 Hz, this doesn´t work. The led blinks (full period) at every 174 seconds. This period stay fixed no matter N is changed. Any idea? Regards Jaraquilibrary ieee; use ieee.std_logic_1164.all; entity clock_gen is generic(N: integer := 50_000_000); port( mclk: in std_logic; rst: in std_logic; clk: out std_logic); end clock_gen; architecture arch of clock_gen is signal cnt: integer := 0; signal clk_en: integer := 0; signal state: integer := 0; begin process(mclk, rst) begin if(rst = '1') then cnt <= 0; clk_en <= 0; state <= 0; elsif(rising_edge(mclk)) then cnt <= cnt + 1; if(cnt = N) then -- this will give you an enable rate of clk/N clk_en <= 1; else clk_en <= 0; end if; if(clk_en = 1) then --do something once every N clocks if(state = 0) then clk <= '1'; state <= 1; else clk <= '0'; state <=0; end if; end if; end if; end process; end arch; - Altera_Forum
Honored Contributor
you shouldnt use clk_en to generate a clock. Forget about generating a 2nd clock. Just use the clk_en directly.