I am trying to read an image file using textio package in vhdl.
If i open an .jpg with notepad , i will get some junk data but actually it is ASCII data . Here i am trying to read these ascii data and convert them into bytes.
below is my code:
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
use ieee.std_logic_textio.all;
entity file_io is
port (
clk: in std_logic;
Data: out std_logic_vector(7 downto 0)
);
end entity;
architecture behav of file_io is
signal test_data : std_logic_vector(7 downto 0);
use ieee.numeric_std.all;
use std.textio.all;
use ieee.std_logic_textio.all;
begin
File_reader:process(clk)
file f : text open read_mode is "C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg";
variable L: line;
variable var_int: integer:= 0;
variable var_char: character;
begin
if rising_edge(clk) then
while not endfile(f) loop
readline(f, L);
read(L, var_char);
var_int := character'pos(var_char);
test_data <= std_logic_vector(to_unsigned(var_int, test_data'length));
end loop;
end if;
Data <= test_data;
end process;
end architecture behav;
testbench:
LIBRARY ieee;
use ieee.std_logic_1164.ALL;
use std.textio.all;
ENTITY file_io_test IS
END file_io_test;
ARCHITECTURE behavior OF file_io_test IS
use work.io.all;
signal clk: std_logic := '0';
signal Data: std_logic_vector(7 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
UUT:
entity work.file_io(behav)
port map (
clk => clk,
Data => Data
);
-- Clock process definitions( clock with 50% duty cycle is generated here.
clk_process :process
begin
clk <= '1';
wait for clk_period/2; --for 5 ns signal is '1'.
clk <= '0';
wait for clk_period/2; --for next 5 ns signal is '0'.
end process;
end behavior;
I am getting only one byte in waveform. expected result is : Every clock cycle new character should be rread and new byte should be obtained.
below is waveform:
below is the image I am trying to read:
You have a while loop placed inside the rising_edge part of your process. What happens is that when the first clock edge occurs, the while loop iterates until the end of the file and gives you the last byte of the input image.
Removing the while loop statement should solve your issue.
The question has a fundamental flaw. You can't use textio to read binary values, it's for text.
See IEEE Std 1076-2008 16.4 Package TEXTIO paragraphs 3 (in part) and 4:
Procedures READLINE, WRITELINE, and TEE declared in package TEXTIO read and write entire lines of a file of type TEXT. Procedure READLINE causes the next line to be read from the file and returns as the value of parameter L an access value that designates an object representing that line. If parameter L contains a non-null access value at the start of the call, the procedure may deallocate the object designated by that value. The representation of the line does not contain the representation of the end of the line. ...
The language does not define the representation of the end of a line. An implementation shall allow all possible values of types CHARACTER and STRING to be written to a file. However, as an implementation is permitted to use certain values of types CHARACTER and STRING as line delimiters, it might not be possible to read these values from a TEXT file.
And that can be demonstrated with your Chrysanthemum.jpg:
It is possible in VHDL to read raw characters one at a time (matching your need).
See IEEE Std 1076-2008 5.5 File types:
So all we have to do is declare a file type and we get these procedures defined implicitly.
We can use them to invoke raw read, without any end of line issues caused by textio:
library ieee;
use ieee.std_logic_1164.all;
entity file_io is
port (
clk: in std_logic;
Data: out std_logic_vector(7 downto 0);
done: out boolean
);
end entity;
architecture foo of file_io is
use ieee.numeric_std.all;
begin
File_reader:
process (clk)
-- "C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg";
constant filename: string := "Chrysanthemum.jpg"; -- local to sim
variable char_val: character;
variable status: FILE_OPEN_STATUS;
variable openfile: boolean; -- FALSE by default
type f is file of character;
file ffile: f;
variable char_count: natural := 0;
begin
if rising_edge (clk) then
if not openfile then
file_open (status, ffile, filename, READ_MODE);
if status /= OPEN_OK then
report "FILE_OPEN_STATUS = " &
FILE_OPEN_STATUS'IMAGE(status)
severity FAILURE;
end if;
report "FILE_OPEN_STATUS = " & FILE_OPEN_STATUS'IMAGE(status);
openfile := TRUE;
else
if not endfile(ffile) then
read(ffile, char_val);
-- report "char_val = " & character'image(char_val);
char_count := char_count + 1;
Data <= std_logic_vector (
to_unsigned(character'pos(char_val),
Data'length) );
end if;
if endfile(ffile) then -- can occur after last character
report "ENDFILE, read " &
integer'image(char_count) & "characters";
done <= TRUE;
FILE_CLOSE(ffile);
end if;
end if;
end if;
end process;
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity file_io_test is
end file_io_test;
architecture behavior of file_io_test is
signal clk: std_logic := '0';
signal data: std_logic_vector(7 downto 0);
signal done: boolean;
constant clk_period: time := 10 ns;
begin
uut:
entity work.file_io(foo)
port map (
clk => clk,
data => data,
done => done
);
clk_process:
process
begin
if not done then
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
else
wait;
end if;
end process;
end architecture behavior;
Now we can have all the characters than can delimit a line show up in our read:
Note that package std.textio is not made visible through any context item.
Related
In my architecture I define a signal of some record type. Each of the record elements is driven in one process only.
The whole record signal is passed to procedures. The procedures will later be placed in a package. Passing the record as type "inout" leeds to all accessed record elements resolving to 'X'.
The code runs in Modelsim and is only for verification (no synthesis needed).
Driving the record elements directly works.
Minimal example; Architecture header:
-- Record type
type tr_Data is record
r1_A : std_logic;
r1_B : std_logic;
end record;
-- Signal definition and initialization
signal sr_Data : tr_Data := (
r1_A => '0',
r1_B => '1'
);
Architecture body:
-- This process only modifies sr_Data.r1_A
prcss_A: process
procedure proc_Modify_A(signal d: inout tr_Data) is
begin
d.r1_A <= not d.r1_A;
end procedure;
begin
wait for 1 us;
--sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
-- This process only modifies sr_Data.r1_B
prcss_B: process
procedure proc_Modify_B(signal d: inout tr_Data) is
begin
d.r1_B <= not d.r1_B;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
This is the Result in Modelsim:
I'm not sure, if this is possible at all. Maybe there are also better solutions to my problem.
Thank's for the help!
This question demonstrates why providing a minimal, complete, and verifiable exampe is desirable for code errors (instead of snippets as here).
Creating a MCVe:
library ieee;
use ieee.std_logic_1164.all;
entity record_process is
end entity;
architecture foo of record_process is
type tr_Data is record
r1_A: std_logic;
r1_B: std_logic;
end record;
signal sr_Data: tr_Data := (r1_A => '0', r1_B => '1');
begin
prcss_A: -- This process only modifies sr_Data.r1_A
process
procedure proc_Modify_A(signal d: inout tr_Data) is
begin
d.r1_A <= not d.r1_A;
end procedure;
begin
wait for 1 us;
-- sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
prcss_B: -- This process only modifies sr_Data.r1_B
process
procedure proc_Modify_B(signal d: inout tr_Data) is
begin
d.r1_B <= not d.r1_B;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
MONITOR:
process (sr_Data)
begin
report
LF & HT &
"sr_Data.r1_A = " & std_logic'image(sr_Data.r1_A) &
LF & HT &
"sr_Data.r1_B = " & std_logic'image(sr_Data.r1_B);
end process;
end architecture;
we see reported behavior that matches the OP's waveform:
record_process.vhdl:44:9:#0ms:(report note):
sr_Data.r1_A = '0'
sr_Data.r1_B = '1'
record_process.vhdl:44:9:#1us:(report note):
sr_Data.r1_A = 'X'
sr_Data.r1_B = '1'
record_process.vhdl:44:9:#1500ns:(report note):
sr_Data.r1_A = 'X'
sr_Data.r1_B = 'X'
The 'X's are caused by the way drivers are associated with subprogram actual parameters:
IEEE Std 1076-2008
4.2 Subprogram declarations
4.2.2.3 Signal parameters
A process statement contains a driver for each actual signal associated with a formal signal parameter of mode out or inout in a subprogram call. Similarly, a subprogram contains a driver for each formal signal parameter of mode out or inout declared in its subprogram specification.
For a signal parameter of mode inout or out, the driver of an actual signal is associated with the corresponding driver of the formal signal parameter at the start of each call. Thereafter, during the execution of the subprogram body, an assignment to the driver of a formal signal parameter is equivalent to an assignment to the driver of the actual signal.
10.7 Procedure call statement
For each formal parameter of a procedure, a procedure call shall specify exactly one corresponding actual parameter. This actual parameter is specified either explicitly, by an association element (other than the actual open) in the association list or, in the absence of such an association element, by a default expression (see 6.5.2).
There's a driver for the actual associated in whole, here a signal of a record type.
(This also tells you Tricky's answer is valid, which reduces the actual to an element of the whole.)
There's another possible solution
Drop the parameter list:
architecture fum of record_process is
type tr_Data is record
r1_A: std_logic;
r1_B: std_logic;
end record;
signal sr_Data: tr_Data := (r1_A => '0', r1_B => '1');
begin
prcss_A: -- This process only modifies sr_Data.r1_A
process
procedure proc_Modify_A is
begin
sr_Data.r1_A <= not sr_Data.r1_A;
end procedure;
begin
wait for 1 us;
-- sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A; -- This works not
wait for 1 us;
wait;
end process;
prcss_B: -- This process only modifies sr_Data.r1_B
process
procedure proc_Modify_B is
begin
sr_Data.r1_B <= not sr_Data.r1_B;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B; -- This works not
wait for 1 us;
wait;
end process;
MONITOR:
process (sr_Data)
begin
report
LF & HT &
"sr_Data.r1_A = " & std_logic'image(sr_Data.r1_A) &
LF & HT &
"sr_Data.r1_B = " & std_logic'image(sr_Data.r1_B);
end process;
end architecture;
which produces:
record_process.vhdl:89:9:#0ms:(report note):
sr_Data.r1_A = '0'
sr_Data.r1_B = '1'
record_process.vhdl:89:9:#1us:(report note):
sr_Data.r1_A = '1'
sr_Data.r1_B = '1'
record_process.vhdl:89:9:#1500ns:(report note):
sr_Data.r1_A = '1'
sr_Data.r1_B = '0'
without any driver conflicts, lacking multiple drivers (14.7.2 Drivers) requiring resolution (14.7.3.4 Signal update) during simulation.
14.7.2 Drivers
Every signal assignment statement in a process statement defines a set of drivers for certain scalar signals. There is a single driver for a given scalar signal S in a process statement, provided that there is at least one signal assignment statement in that process statement and that the longest static prefix of the target signal of that signal assignment statement denotes S or denotes a composite signal of which S is a subelement. Each such signal assignment statement is said to be associated with that driver. Execution of a signal assignment statement affects only the associated driver(s).
The longest static prefix is defined in 8. Names:
8.1 General
A static signal name is a static name that denotes a signal. The longest static prefix of a signal name is the name itself, if the name is a static signal name; otherwise, it is the longest prefix of the name that is a static signal name. ...
where the longest static prefix now includes record elements as opposed to actual signals of a record type associated in whole.
This is possible because a subprogram is a sequence of statements (4.2 Subprogram bodies) and the procedures are declared within the scope of the declaration of sr_Data (12.1 Declarative region, 12.2 Scope of declarations, 12.3 Visibility).
The error is here because the procedures take in a record type. When this happens, they create a driver on the entire record, not just the elements driven internally. Hence you have multiple drivers because the same signal is driven from multiple processes.
If you want to drive only the elements, make the procedures take an inout of std_logic type and only pass in the signal record elements. This way, each process is only driving a single element of the record.
-- This process only modifies sr_Data.r1_A
prcss_A: process
procedure proc_Modify_A(signal d: inout std_logic) is
begin
d <= not d;
end procedure;
begin
wait for 1 us;
--sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A(sr_Data.r1_A); -- This works not
wait for 1 us;
wait;
end process;
-- This process only modifies sr_Data.r1_B
prcss_B: process
procedure proc_Modify_B(signal d: inout std_logic) is
begin
d <= not d;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B(sr_Data.r1_B); -- This works not
wait for 1 us;
wait;
end process;
No time now for an explanation but the following solution should achieve exactly what you are asking for:
Architecture header:
-- Record type
type tr_Data is record
r1_A : std_logic;
r1_B : std_logic;
end record;
constant TR_DATA_INIT : tr_Data := (
r1_A => 'Z',
r1_B => 'Z'
);
-- Signal definition and initialization
signal sr_Data : tr_Data := (
r1_A => '0',
r1_B => '1'
);
Architecture body:
-- This process only modifies sr_Data.r1_A
prcss_A: process
procedure proc_keep_A(signal d: inout tr_Data) is
begin
d <= TR_DATA_INIT;
d.r1_A <= d.r1_A;
end procedure;
procedure proc_Modify_A(signal d: inout tr_Data) is
begin
d.r1_A <= not d.r1_A;
end procedure;
begin
proc_keep_A(sr_Data); -- needed only at the very beginning of the process
wait for 1 us;
--sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A(sr_Data); -- This works too
wait for 1 us;
wait;
end process;
-- This process only modifies sr_Data.r1_B
prcss_B: process
procedure proc_keep_B(signal d: inout tr_Data) is
begin
d <= TR_DATA_INIT;
d.r1_B <= d.r1_B;
end procedure;
procedure proc_Modify_B(signal d: inout tr_Data) is
begin
d.r1_B <= not d.r1_B;
end procedure;
begin
proc_keep_B(sr_Data); -- needed only at the very beginning of the process
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B(sr_Data); -- This works too
wait for 1 us;
wait;
end process;
Thanks for all the detailed informations. I learned a lot through that.
Based on your answers I found a solution. For my purpose, it is to use a resolved type and init it at the beginning of each process as Giampietro Seu suggested. This also enables me to put non-resolved types like integer, time etc. in the record.
Here is the full reproducable minimal example.
Entity:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.pkg_Minimal.all;
entity eMinimalExample is
end entity;
architecture aMinimal of eMinimalExample is
-- Signal of resolved subtype
signal sr_Data : rtr_Data;
begin
-- This process only modifies sr_Data.r1_A / ri_A
prcss_A: process
begin
proc_Init_A(sr_Data); -- Only needed once
wait for 1 us;
proc_Modify_A(sr_Data);
wait for 1 us;
wait;
end process;
-- This process only modifies sr_Data.r1_B / ri_B
prcss_B: process
begin
proc_Init_B(sr_Data); -- Only needed once
wait for 1.5 us;
proc_Modify_B(sr_Data);
wait for 1 us;
wait;
end process;
prcss_Monitor: process (sr_Data)
begin
report
LF & HT &
"sr_Data.r1_A = " & std_logic'image(sr_Data.r1_A) &
LF & HT &
"sr_Data.r1_B = " & std_logic'image(sr_Data.r1_B) &
LF & HT &
"sr_Data.ri_A = " & integer'image(sr_Data.ri_A) &
LF & HT &
"sr_Data.ri_B = " & integer'image(sr_Data.ri_B);
end process;
end architecture;
Package:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
package pkg_Minimal is
-- Record type
type tr_Data is record
r1_A : std_logic;
ri_A : integer;
r1_B : std_logic;
ri_B : integer;
end record;
-- Array of record
type ta_Data is array(natural range <>) of tr_Data;
-- Resolution function for record
function f_resolve_Data (ca_Data: in ta_Data) return tr_Data;
-- Resolved record subtype
subtype rtr_Data is f_resolve_Data tr_Data;
-- Init A with init values and B with recessive values
procedure proc_Init_A (signal d: inout rtr_Data);
-- Init B with init values and A with recessive values
procedure proc_Init_B (signal d: inout rtr_Data);
-- Modify A only
procedure proc_Modify_A (signal d: inout rtr_Data);
-- Modify B only
procedure proc_Modify_B (signal d: inout rtr_Data);
end package;
package body pkg_Minimal is
-- Record init values
constant cr_Data_Init : tr_Data := (
r1_A => '0',
ri_A => 10,
r1_B => '1',
ri_B => 20
);
-- Recessive values for resolution function
constant cr_Data_Recessive : tr_Data := (
r1_A => 'Z',
ri_A => integer'low, -- Lowest value is burned,
r1_B => 'Z', -- we can't use it anymore
ri_B => integer'low
);
-- Resolution function for record
function f_resolve_Data (constant ca_Data: in ta_Data) return tr_Data is
variable vr_Data : tr_Data := cr_Data_Recessive;
begin
for i in ca_Data'range loop
if cr_Data_Recessive.r1_A /= ca_Data(i).r1_A then
vr_Data.r1_A := ca_Data(i).r1_A;
end if;
if cr_Data_Recessive.r1_B /= ca_Data(i).r1_B then
vr_Data.r1_B := ca_Data(i).r1_B;
end if;
if cr_Data_Recessive.ri_A /= ca_Data(i).ri_A then
vr_Data.ri_A := ca_Data(i).ri_A;
end if;
if cr_Data_Recessive.ri_B /= ca_Data(i).ri_B then
vr_Data.ri_B := ca_Data(i).ri_B;
end if;
end loop;
return vr_Data;
end function;
procedure proc_Init_A(signal d: inout rtr_Data) is
begin
d <= cr_Data_Recessive;
d.r1_A <= cr_Data_Init.r1_A;
d.ri_A <= cr_Data_Init.ri_A;
end procedure;
procedure proc_Init_B(signal d: inout rtr_Data) is
begin
d <= cr_Data_Recessive;
d.r1_B <= cr_Data_Init.r1_B;
d.ri_B <= cr_Data_Init.ri_B;
end procedure;
procedure proc_Modify_A(signal d: inout rtr_Data) is
begin
d.r1_A <= not d.r1_A;
d.ri_A <= d.ri_A + 1;
end procedure;
procedure proc_Modify_B(signal d: inout rtr_Data) is
begin
d.r1_B <= not d.r1_B;
d.ri_B <= d.ri_B + 1;
end procedure;
end package body;
Output:
** Note:
sr_Data.r1_A = '0'
sr_Data.r1_B = '1'
sr_Data.ri_A = 10
sr_Data.ri_B = 20
Time: 0 ps Iteration: 0 Instance: /eminimalexample
** Note:
sr_Data.r1_A = '1'
sr_Data.r1_B = '1'
sr_Data.ri_A = 11
sr_Data.ri_B = 20
Time: 1 us Iteration: 1 Instance: /eminimalexample
** Note:
sr_Data.r1_A = '1'
sr_Data.r1_B = '0'
sr_Data.ri_A = 11
sr_Data.ri_B = 21
Time: 1500 ns Iteration: 1 Instance: /eminimalexample
Trying to make a UART Transmitter to send a data from FPGA to PC; 9600 baudrate, 8-bits, no parity, 1 start & stop bit; I wrote a code with VHDL, run synthesis and simulate it in a way I like it to be. I wanted to see it with BASYS 3 FPGA, After created constraints, Run Implementation issued an error in which its called "Opt_Design Error".
library ieee;
use ieee.std_logic_1164.all;
entity rs232_omo is
generic(clk_max:integer:=10400); --for baudrate
port(
clk : in std_logic;
rst : in std_logic;
start : in std_logic;
input : in std_logic_vector(7 downto 0);
done : out std_logic;
output : out std_logic;
showstates: out std_logic_vector(3 downto 0)
);
end entity;
architecture dataflow of rs232_omo is
type states is (idle_state,start_state,send_state,stop_state);
signal present_state,next_state : states;
signal data,data_next : std_logic;
begin
process(clk,rst)
variable count : integer range 0 to clk_max;
variable index : integer range 0 to 10;
begin
if rst='1' then
present_state<=idle_state;
count:=0;
data<='1';
done<='0';
elsif rising_edge(clk) then
present_state<=next_state;
count:=count+1;
index:=index+1;
data<=data_next;
end if;
end process;
process(present_state,data,clk,rst,start)
variable count : integer range 0 to clk_max;
variable index : integer range 0 to 10;
begin
done<='0';
data_next<='1';
case present_state is
when idle_state =>
showstates<="1000";
data_next<='1';
if start='1' and rst='0' then
count:=count+1;
if count=clk_max then
next_state<=start_state;
count:=0;
end if;
end if;
when start_state =>
showstates<="0100";
data_next<='0';
count:=count+1;
if count=clk_max then
next_state<=send_state;
count:=0;
end if;
when send_state =>
showstates<="0010";
count:=count+1;
data_next<=input(index);
if count=clk_max then
if index=7 then
index:=0;
next_state<=stop_state;
else
index:=index+1;
end if;
count:=0;
end if;
when stop_state =>
showstates<="0001";
count:=count+1;
if count=clk_max then
next_state<=idle_state;
done<='1';
count:=0;
end if;
end case;
end process;
output<=data;
end architecture;
This's the error message in detail
"[DRC MDRV-1]Multiple Driver Nets:Net done_OBUF has multiple drivers:
done_OBUF_inst_i_1/O,and done_reg/Q"
"[Vivado_Tcl 4-78] Error(s) found during DRC. Opt_Design not run."
What would be the reason for this error?
You are assigning done both in the first and the second process, which is exactly what the implementation is complaining about, you cannot have multiple drivers.
Remove done<='0'; from the first process and it should complete the implementation.
(I didn't check if the rest of the code is doing exactly what you want.)
I have this problem with the VHDL synthesis. I read in multiple articles that the "wait" statement is synthesizable if I only use one "wait until"/process, so that's what I did. So I tried to make a counter which shows at what floor I am (my project consists of an elevator in Logic Design), and it should open the doors for 5 seconds at floors which were ordered. The problem is with the wait statement. I don't know what to replace it to make it work in ISE too.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity counter is
port(clk1: in std_logic;
enable2:in std_logic;
input_mux: in std_logic;
dir: in std_logic;
reset,s_g,s_u: in std_logic;
q_open: out std_logic;
q: out std_logic_vector(3 downto 0));
end counter;
architecture c1 of counter is
signal flag: std_logic:='0';
component test
port(clock: in std_logic;
a: in std_logic_vector(3 downto 0);
notify: out std_logic);
end component;
begin
delay: test port map(clk1,"0101",flag);
process
variable temp:std_logic_vector(3 downto 0):="0000";
variable q_open_var:std_logic:='0';
begin
if (enable2='1') then
if (s_g='1' and s_u='1') then
if (RESET='1') then
temp:="0000";
elsif (CLK1'EVENT and CLK1='1') then
if (DIR='1') then
temp:=temp+1;
elsif(DIR='0') then
temp:=temp-1;
end if;
end if;
end if;
end if;
if (input_mux='1') then
q_open_var:='1';
q_open<=q_open_var;
wait until (flag'event and flag='1');
q_open_var:='0';
end if;
q<=temp;
q_open<=q_open_var;
wait on clk1, reset;
end process;
end c1;
Although this structure is supported, you pushed over the limit of what is supported. The synthesis tool must generate registers from what you code. A register does have a clock and a reset input, but the synthesis tool does not know the words clk1 and reset. I.e. is you write
wait on clk1, reset;
The tool will not know what the reset is, nor what the clock is. Actually, both signals are considered clock triggers.
But you design is more problematic, as you have if-statements before the asynchronous reset and clock trigger. Although clock-gating is supported, you probably did not intend it.
Then there is a /second/ clock trigger in you statement: wait until (flag'event and flag='1');. I don't know what you are doing there, but how would you imagine this being realized in hardware?
You should really stick to standard/advised coding style for predictable behavior. I.e.
library ieee;
use ieee.numeric_std.all;
[...]
signal temp : unsigned(3 downto 0) := (others => '0');
begin
temp_proc: process(clk1, reset)
variable q_open_var : std_logic := '0';
begin
if rising_edge(clk1) then
if enable2='1' and s_g='1' and s_u='1' then
if dir = '1' then
temp <= temp + 1;
elsif dir = '0' then
temp <= temp - 1;
end if;
end if;
end if;
if reset = '1' then
temp <= (others => '0');
end if;
end process;
q <= std_logic_vector(temp);
(I left out the q_open part, as it is unclear what you want. Make a SEPARATE process for that, as it is not dependent on reset)
p.s. I like the five lines of end if; the most ;) Please use proper indenting next time. And use 'elsif' not 'else if'.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_SIGNED.all;
use std.env.all;
USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;
ENTITY tb_top IS
END tb_top;
ARCHITECTURE behavior OF tb_top IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT c4b
PORT(
clock : IN std_logic;
reset : IN std_logic;
count : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal clock : std_logic := '0';
signal reset : std_logic := '0';
--Outputs
signal count : STD_LOGIC_vector(3 downto 0) := "0000";
-- Clock period definitions
constant period : time := 100 ns;
-- Opening the file in write mode
file myfile : TEXT open write_mode is "fileio.txt";
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: c4b PORT MAP (
clock => clock,
reset => reset,
count => count
);
clock_process :process --providing clock to the counter
begin
clock <= '1';
wait for period/2;
clock <= '0';
wait for period/2;
end process;
write_process: process
variable abd: LINE;
--variable val1: integer;
begin
--val1 := CONV_INTEGER(count); --saw this in another program. even they converted a std_logic_vector to integer. didn't work!
loop --tried the infinite loop to check for the value 1111,
if (count = "1111") then --so that as soon as count reaches the value 1111,
finish (0); --it would stop, because i only need to write one entire sequence of the cycle to the file!!
else
write (abd, count);
writeline (myfile, abd);
end if;
end loop;
end process;
-- Stimulus process
stim_process: process
begin
reset <= '0'; --because it only works when reset is 0!
wait for 100 ns;
if (count = "1111") then --the value is written to the text file in a continuous loop,
finish (0); --which makes he file size go to as much as 1 GB
end if; --thus to stop it at exactly one cycle!
end process;
END;
So, basically what I want to do here is let the counter count up from 0000 too 1111 and then write the entire sequence to a text file. But I only wish to write exactly just one cycle. Hence I've added a loop to check the same. Here in the code above I'm not able to simulate the testbench properly. When I don't include the write_process part of the code, the simulation works perfectly, giving me exactly just one cycle! (Simulator result w/o write_process picture no 1). But when I try to use the write_process, not only does it not simulate (Simulator result after adding the write_process) picture no 2, it also writes UUUU continuously to the file, until I close the ISim, and file size goes to at least a few hundred MBs! Please help!
Without the entity/architecture for c4b no one can duplicate your error, it's visible however.
Note that the write process has no sensitivity list nor wait statement and a loop statement that won't exit unless external stimuli is provided - if (count = "1111") then ...
It doesn't seem proper to be using finish in both stim_process and write_process, there's no guarantee of execution order you can lose the last write (if you cure the write process defect).
You have four unused use clauses (numeric_std, std_logic_arith, std_logic_signed, std_logic_textio, with VHDL -2008).
So, basically what I want to do here is let the counter count up from 0000 too 1111 and then write the entire sequence to a text file.
There's nothing in your code that spools up output until your simulation finishes. Writing a line to file textio.txt occurs for events driving the write process.
Adding a model for c4b:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity c4b is
port (
clock: in std_logic;
reset: in std_logic;
count: out std_logic_vector(3 downto 0)
);
end entity;
architecture foo of c4b is
begin
process (clock, reset)
begin
if reset = '1' then
count <= (others => '0');
elsif rising_edge (clock) then
count <= count + 1;
end if;
end process;
end architecture;
Removing unused use clauses (not strictly necessary):
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
-- USE IEEE.NUMERIC_STD.ALL;
-- IEEE.STD_LOGIC_ARITH.all;
-- use IEEE.STD_LOGIC_SIGNED.all;
use std.env.all;
-- USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;
Changing the write_process to not endlessly loop:
-- write_process: process
-- variable abd: LINE;
-- --variable val1: integer;
-- begin
-- --val1 := CONV_INTEGER(count); --saw this in another program. even they converted a std_logic_vector to integer. didn't work!
-- loop --tried the infinite loop to check for the value 1111,
-- if (count = "1111") then --so that as soon as count reaches the value 1111,
-- finish (0); --it would stop, because i only need to write one entire sequence of the cycle to the file!!
-- else
-- write (abd, count);
-- writeline (myfile, abd);
-- end if;
-- end loop;
-- end process;
write_process:
process
variable abd: LINE;
begin
wait on count;
wait for 100 ns;
write (abd, count);
writeline (myfile, abd);
if count = "1111" then
finish (0);
elsif IS_X(count) then
report "count contains a metavalue and may not increment";
finish (-1);
end if;
end process;
The wait 100 ns; accommodates a reset to insure the counter can increment. It's possible to provide a design description of c4b that doesn't depend on reset. For purposes here, the supplied c4b doesn't do that. The wait 100 ns also provides the sample interval for count, which from the component declaration for c4b is free running, driven by clock events.
Changing the stim_process to not finish and wait instead:
-- -- Stimulus process
-- stim_process: process
-- begin
-- reset <= '0'; --because it only works when reset is 0!
-- wait for 100 ns;
-- if (count = "1111") then --the value is written to the text file in a continuous loop,
-- finish (0); --which makes he file size go to as much as 1 GB
-- end if; --thus to stop it at exactly one cycle!
-- end process;
-- END;
stim_process:
process
begin
reset <= '1';
wait for 100 ns;
reset <= '0';
wait for 100 ns;
wait;
end process;
Notice this also provides a reset interval seen on the following waveform.
And that gives us:
With the contents of textio.txt:
more fileio.txt
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
It's also possible to end simulation after detecting count is "1111" by stopping clock, avoiding the use of the finish procedure. Along with a write procedure supplied using the Synopsys package std_logic_texio:
procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
This would allow the use of VHDL simulators complying to VHDL standard revisions earlier than -2008.
I found this code which is a part of Exponentiation implementation, I believe this code is for parallel load register, the code had many mistakes, yet I tried to fix it and simplify it(simplification is to make it work), the original code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity REG is --Register entity
Port ( CLK,set,reset,In_LOAD : in std_logic;
Din_p: in std_logic_vector(m-1 to 0);
Din_s: in std_logic;
Dout: out std_logic);
end REG;
architecture behavior of REG is
signal Q_temp: std_logic_vector(m-1 down to 0);
begin
Dout<=”0”;
comb:process(In_LOAD,Din_s)
begin
if(In_LOAD=”1”) then Q_temp<=Din_p;end if;
end process comb;
state: process(CLK,set,reset)
begin
if(reset=”1”) then Q_temp<=(others=>”0”);end if;
if(set=”1”) then Q_temp<= (others=>”1”);
elsif(CLK’event and CLK=”1”) then
Q_temp:=Din_p & Q_temp(m-1 down to 1);
end if;
Dout<= Q_temp(0);
end process state;
end behavior;
while the code I modified is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity REG2 is --Register entity
generic (m: integer := 4);
Port ( CLK,In_LOAD : in std_logic;
Din_p: in std_logic_vector(m-1 to 0);
Dout: out std_logic);
end REG2;
architecture behavior of REG2 is
signal Q_temp: std_logic_vector(m-1 downto 0);
begin
Dout<='0';
process(In_LOAD, Din_p, CLK)
begin
if (CLK'event and CLK='1') then
Q_temp <=Din_p;
elsif (In_LOAD='1') then
Q_temp <= Din_p & Q_temp(m-1 downto 1);
end if;
end process;
Dout <= Q_temp(0);
end behavior;
so my questions are : 1- why I'm getting this error :(Error (10344): VHDL expression error at REG2.vhd(18): expression has 0 elements, but must have 4 elements)?
2- this is a code for parallel load register, right?
thx
Plenty of things are wrong with your code (and the original code).
use the correct quote character " for bit strings and ' for bits instead of ”
downto is one word, not down to
m is not declared; perhaps this is supposed to be a generic?
Assign to Q_temp using signal assignment <= instead of variable assignment :=
Sensitivity lists for both your processes are incomplete
As #Morten mentions: the direction of Din_p should probably downto instead of to
Bonus (pet peeve): don't use IEEE.STD_LOGIC_ARITH and IEEE.STD_LOGIC_UNSIGNED, because they are not properly standardized. Use ieee.numeric_std instead.