I am trying to make a "Product Based Planning" diagram in Dot, but I can't quite figure out how to get the structure, I am looking for.
Here's the code I have wrote so far:
graph ProductBasedPlanning
{
node [shape="box"];
rankdir = "TB";
splines="FALSE";
"Main product" -- {"Functionality 1" "Functionality 2"}
"Functionality 1" -- {"Functionality 1a" "Functionality 1b"}
}
But I am looking to create something like this:
So, how do I get the lines to move in 90 degree angles?
and how do I "stack" the boxes like in the example?
Thanks for your help.
I used rank="same" and shape="point" node.
graph ProductBasedPlanning
{
node [shape="box"];
rankdir = "TB";
splines=false
"xm1" [shape="point"]
"xm2" [shape="point"]
"xm3" [shape="point"]
"Main product" -- "xm2"
{
rank="same"
"xm1" -- "xm2" -- "xm3" [constraint=false]
}
"xm1" -- "Functionality 1"
"xm2" -- "Functionality 2"
"xm3" -- "Functionality 3"
"Functionality 1" -- "x1a" -- "x1b" -- "x1c"
"Functionality 2" -- "x2a" -- "x2b" -- "x2c"
"Functionality 3" -- "x3a" -- "x3b" -- "x3c"
{
rank="same"
"x1a" [shape="point"]
"x1a" -- "Functionality 1a"
}
{
rank="same"
"x1b" [shape="point"]
"x1b" -- "Functionality 1b"
}
{
rank="same"
"x1c" [shape="point"]
"x1c" -- "Functionality 1c"
}
{
rank="same"
"x2a" [shape="point"]
"x2a" -- "Functionality 2a"
}
{
rank="same"
"x2b" [shape="point"]
"x2b" -- "Functionality 2b"
}
{
rank="same"
"x2c" [shape="point"]
"x2c" -- "Functionality 2c"
}
{
rank="same"
"x3a" [shape="point"]
"x3a" -- "Functionality 3a"
}
{
rank="same"
"x3b" [shape="point"]
"x3b" -- "Functionality 3b"
}
{
rank="same"
"x3c" [shape="point"]
"x3c" -- "Functionality 3c"
}
}
Related
I have a problem with prosedeur supression() when inserting an etudent (more than one) and deleted by suprrision Procedure and make a search about that item I delete the program and I guess the problem is in ? prosedur supression()`. Look at it first.
I wish that clear thank u guys now
declartion to types student and moudle and note
Program liste_des_etudiants;
Type
date = Record
jour,mois,anee : Integer;
End;
ptr_etu = ^etudiant;
etudiant = Record
matricule : String;
nom,prenom,adress : String;
date_n : date;
suiv : ptr_etu;
End;
ptr_mod = ^module;
module = Record
code,libelle : String;
credit,coeff : Integer;
suiv : ptr_mod;
End;
ptr_note = ^note;
note = Record
matricule : String;
code : String;
note : Integer;
suiv : ptr_note;
End;
Var
choix : String;
liste_etudiant : ptr_etu ;
liste_note : ptr_note;
liste_module : ptr_mod;
Procedure supression etudent
Procedure supression(Var etu:ptr_etu;module:ptr_mod;note:ptr_note );
var
choix,matr,code : String;
current,prvious,Next: ptr_etu;
current_note,privous_note :ptr_note;
privous_code,current_code: ptr_mod;
begin
Repeat
Repeat
Writeln('pour supression un etudiant tapez 1');
Writeln('pour supression un note tapez 2');
Writeln('pour supression un module tapez 3');
Writeln('pour sortir tapez e ');
Readln(choix);
Until ((choix='1') Or (choix='2') Or (choix='3') Or (choix='e') Or (choix='E'));
If (choix='1') Then
Begin
// I guess the porblem is here but i don't know is it
// initcation de node
current := etu ;
Writeln('donner son matricule') ;
Readln(matr);
// traitement to the if the node we wanna delet is the
// first one
While((etu<>Nil) And(etu^.matricule=matr))Do
etu:= etu^.suiv;
While ((current<>Nil) and (current^.suiv<>nil)) Do
Begin
next:=etu^.suiv;
if (next^.matricule=matr) then
begin
current^.suiv:=next^.suiv;
end
Else
current:=current^.suiv;
end;
if (current =nil) then
writeln('l ''''etudiant n''''est pas trouvee');
Until ((choix='e') Or(choix='E'));
end;
Main
Begin
Repeat
Repeat
Writeln('tapez:');
Writeln('1):pour insertion');
Writeln('2):pour modification');
Writeln('3):pour supression');
Writeln('4):pour recherche');
Writeln('(e)pour sortir');
Readln(choix);
Until ((choix='1') Or (choix='2') Or (choix='3') Or (choix='4') Or (choix='e'));
If (choix='1') Then
insertion(liste_etudiant, liste_module,liste_note)
Else If (choix='2') Then
modification(liste_etudiant, liste_module,liste_note)
Else If (choix='3') Then
supression(liste_etudiant,liste_module,liste_note)
Else if (choix='4') Then
recherche(liste_etudiant, liste_module,liste_note)
Until ((choix='e') Or (choix='E'));
End.
I'm very confused about vunit testing, especially the link between tests and the way they are reset.
Please take a look at next minimal example:
device under test
Device has one inner state that latch on 1 when input goes to 1
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity dut is
port(
A : in std_logic;
B : out std_logic := '0'
);
end entity;
architecture RTL of dut is
begin
-- will latch when A goes to '1'
-- stay 1 forever
B <= '1' when A = '1';
end architecture;
testbench
test1 : Dut inner state to '1'
test2 : Dut has been reset in between test1 and test2
test3 : Does not set dut inner state to '1' because C, which is set at start of process, but somehow reset to initial state (1) before test.
test4 : Does not set dut inner state to '1' because D, which is set at start of process, but somehow reset to initial state (U) before test.
test5 : Does not set dut inner state to '1' because E, which is set at start of loop, but somehow reset to initial state (U) before test. Which seems contrary to the the documentation (or most likely, I don't get it)
test6 : Dut inner state is set, F is not reset.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
library vunit_lib;
use vunit_lib.run_pkg.all;
use vunit_lib.check_pkg.all;
library libdut;
use libdut.all;
entity some_tb is
generic (runner_cfg : string);
end entity;
architecture arch of some_tb is
signal A, B, C : std_logic := '0';
signal D, E, F : std_logic;
begin
invdut: entity dut port map (A => A, B => B);
F <= '1';
main: process begin
test_runner_setup(runner, runner_cfg);
C <= '1';
D <= '1';
while test_suite loop
E <= '1';
if run("test 1") then
check_equal(B, '0', "test 1.1");
A <= '1';
wait for 1 ns;
check_equal(A, '1', "test 1.2");
elsif run("test 2") then
check_equal(A, '0', "test 2.1");
check_equal(B, '0', "test 2.2");
elsif run("test 3") then
A <= C;
wait for 1 ns;
check_equal(B, '0', "test 3.1");
elsif run("test 4") then
A <= D;
wait for 1 ns;
check_equal(A, 'U', "test 4.1");
check_equal(B, '0', "test 4.2");
elsif run("test 5") then
A <= E;
wait for 1 ns;
check_equal(A, 'U', "test 5.1");
check_equal(B, '0', "test 5.2");
elsif run("test 6") then
A <= F;
wait for 1 ns;
check_equal(A, '1', "test 6.1");
check_equal(B, '1', "test 6.2");
end if;
end loop;
test_runner_cleanup(runner); -- Simulation ends here
wait;
end process;
end architecture;
Vunit file
#!/usr/bin/env python3
from pathlib import Path
from vunit import VUnit
SRC_PATH = Path(__file__).parent / "src"
TEST_PATH = Path(__file__).parent / "test"
def create_testsuite(project):
lib = project.add_library("libdut")
lib.add_source_files(SRC_PATH / "*.vhdl")
libuart_test = project.add_library("libdut_test")
libuart_test.add_source_files(TEST_PATH / "*.vhdl")
The question(s)
This seems very random to me. I will ask multiple question into one, because, most likely, they are tightly correlated.
When are the signal reset ?
Is every test run in a different simulation or are they "in series" with chances of side effect ?
In which foremost case, why is there a loop ?
By default VUnit will run each test case in a separate simulation but it is possible to change this behavior using the run_all_in_same_sim attribute. The rationale for this is described here: https://vunit.github.io/run/user_guide.html#running-test-cases-independently
Having the loop allow for this option but there are also other reasons as explained in https://vunit.github.io/run/user_guide.html#running-a-vunit-testbench-standalone. In general, https://vunit.github.io/run/user_guide.html is a good source for the details about VUnit execution.
The reason your signal assignments do not work as you expect is due to delta cycles. When A is assigned E in test 5 it is done in the same delta cycle as E is assigned 1 since nothing between the two assignments consume time. The new value of E is not present when A is assigned E. Instead A gets the previous value of E (U).
The difference between test 5 and 6 is that F is assigned 1 before the test_runner_setup procedure completes. A procedure can consume time and in this case it does, at least delta cycles. When A is assigned F the new value of F is present.
I'm not sure how well you know the concept of delta cycles and the difference between signals and variables. If not, I suggest that you look into that.
In a VHDL testbench, I have a function that parses a csv file in order to initialize a test array.
When running the function in the elaboration phase to set the values of a constant, the function behaves differently than when using the same function in simulation (e.g. initializing a signal during a reset)
The function code is:
constant cn_DATA_WIDTH : natural := 10;
constant cn_DATA_DEPTH : natural := 400;
type tav_data_array is array (0 to cn_DATA_DEPTH - 1) of std_logic_vector(cn_DATA_WIDTH - 1 downto 0);
function f_init_data_from_file (
s_file_path : in string;
i_column_index : in integer := 0
) return tav_data_array is
-- file parsing
file f_data_file_buf : text is in s_file_path;
variable vl_data_file_line : line;
variable vi_data_entry : integer;
variable vc_comma : character;
variable vb_good_num : boolean;
-- destination
variable vav_data_array : tav_data_array;
begin
-- Skip first line that contains header
readline (f_data_file_buf, vl_data_file_line);
for line_index in vav_data_array'range loop
readline (f_data_file_buf, vl_data_file_line);
read (vl_data_file_line, vi_data_entry, vb_good_num);
assert vb_good_num
report "Failed reading file : " & s_file_path
& ", at line = " & integer'image(line_index)
& ", at column = 0"
severity failure;
for column_index in 1 to i_column_index loop
read(vl_data_file_line, vc_comma);
read(vl_data_file_line, vi_data_entry, vb_good_num);
assert vb_good_num
report "Failed reading file : " & s_file_path
& ", at line = " & integer'image(line_index)
& ", at column = " & integer'image(column_index)
severity failure;
end loop;
vav_data_array(line_index) := std_logic_vector(to_unsigned(vi_data_entry, cn_DATA_WIDTH));
end loop;
return vav_data_array;
end function;
Function usage in elaboration:
constant cav_data : tav_data_array :=
f_init_data_from_file (
s_file_path => "my_path" ,
i_column_index => 3
);
Result: The test array is not initialized with the expected data. The data used for the initialization is column 0 instead of column 3.
Function usage in elaboration:
signal sav_data : tav_data_array;
-- ...
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
sav_data <=
f_init_data_from_file (
s_file_path => "my_path" ,
i_column_index => 3
);
else
-- ...
end if;
end if;
end process;
In this case, the data used for initialization is the proper one. Column 3 is used as expected.
Is there a reason for this different behavior? Or is this a bug with the tools I am using for simulation (Xilinx Vivado 2018.2)?
EDIT to create MRVE:
As requested, this is a minimal reproducible example. Some of the parameters
Source code:
-- MRVE
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
-- File parsing
use STD.textio.all;
use ieee.std_logic_textio.all;
entity file_bug_mrve is
end file_bug_mrve;
architecture a_file_bug_mrve of file_bug_mrve is
-- Actual data are 12 bits
constant cn_DATA_WIDTH : natural := 12;
constant cn_DATA_DEPTH : natural := 4; -- testbench is planned for 400 high priority cycles
type tav_data_array is array (0 to cn_DATA_DEPTH - 1) of std_logic_vector(cn_DATA_WIDTH - 1 downto 0);
-- Parse csv data file to retrieve all entries at specified columns
function f_init_data_from_file (
s_file_path : in string;
i_column_index : in integer := 0
) return tav_data_array is
-- file parsing
file f_data_file_buf : text is in s_file_path;
variable vl_data_file_line : line;
variable vi_data_entry : integer;
variable vc_comma : character;
variable vb_good_num : boolean;
-- destination
variable vav_data_array : tav_data_array;
begin
-- Skip first line
readline (f_data_file_buf, vl_data_file_line);
for line_index in vav_data_array'range loop
readline (f_data_file_buf, vl_data_file_line);
read (vl_data_file_line, vi_data_entry, vb_good_num);
assert vb_good_num
report "Failed reading file : " & s_file_path
& ", at line = " & integer'image(line_index)
& ", at column = 0"
severity failure;
for column_index in 1 to i_column_index loop
read(vl_data_file_line, vc_comma);
read(vl_data_file_line, vi_data_entry, vb_good_num);
assert vb_good_num
report "Failed reading file : " & s_file_path
& ", at line = " & integer'image(line_index)
& ", at column = " & integer'image(column_index)
severity failure;
end loop;
vav_data_array(line_index) := std_logic_vector(to_unsigned(vi_data_entry, cn_DATA_WIDTH));
end loop;
return vav_data_array;
end function;
constant cs_RSP_DATA_IN_FILE_PATH : string := "../../src/xls/file_bug_mrve.csv";
constant cn_RSP_DATA_IN_COLUMN_INDEX : natural := 3;
-- registers emulation
-- Setting init data to be processed in elaboration does not work
-- Data will be initialized with first column instead of third
signal sav_data : tav_data_array :=
f_init_data_from_file (
s_file_path => cs_RSP_DATA_IN_FILE_PATH ,
i_column_index => cn_RSP_DATA_IN_COLUMN_INDEX
);
-- infa Simulation
constant ct_CLOCK_PERIOD_100 : time := 10 ns;
constant ct_TEST_COMPLETION_TIME : time := ct_CLOCK_PERIOD_100 * 10;
signal s_clk : std_logic;
signal s_rst : std_logic;
signal sb_end : boolean := false;
begin
-- -----------------------------------------------------------------------------------------------------------------
-- Clock process definitions
-- -----------------------------------------------------------------------------------------------------------------
p_Clock_100 : process
begin
s_clk <= '0';
wait for ct_CLOCK_PERIOD_100/2;
s_clk <= '1';
wait for ct_CLOCK_PERIOD_100/2;
if sb_end then
wait;
end if;
end process;
-- -----------------------------------------------------------------------------------------------------------------
-- Main Stimulus process
-- -----------------------------------------------------------------------------------------------------------------
p_stimulous : process
begin
--
s_rst <= '0';
-- 1 clock cycle reset to avoid loading file multiple times
wait until rising_edge(s_clk);
s_rst <= '1';
wait until rising_edge(s_clk);
s_rst <= '0';
wait for ct_TEST_COMPLETION_TIME;
sb_end <= true;
end process;
p_main : process(s_clk)
begin
if rising_edge(s_clk) then
if s_rst = '1' then
-- Setting init data to be processed in simulation works
-- Data will be initialized with forth column as expected
sav_data <=
f_init_data_from_file (
s_file_path => cs_RSP_DATA_IN_FILE_PATH ,
i_column_index => cn_RSP_DATA_IN_COLUMN_INDEX
);
else
-- Nothing to do in MRVE
end if;
end if;
end process p_main;
end a_file_bug_mrve;
CSV file:
Ch0,Ch1,Ch2,Ch3
1,5,9,13
2,6,10,14
3,7,11,15
4,8,12,16
I have a very simple I2C bit-banging library for ATTINY85.
#define PORT_SDA PB0
#define PORT_SCL PB2
#define SIGNAL_HIGH(PORT) PORTB |= ( 1 << PORT )
#define SIGNAL_LOW(PORT) PORTB &= ~( 1 << PORT )
void LED_ON(void);
void LED_OFF(void);
void i2c_init(void);
void i2c_start(void);
void i2c_read(void);
void i2c_stop(void);
void i2c_write(uint8_t byte);
void i2c_init()
{
DDRB |= ( 1 << PORT_SDA );
DDRB |= ( 1 << PORT_SCL );
}
void LED_ON( void )
{
PORTB |= 0b00000010;
}
void LED_OFF( void )
{
PORTB &= 0b111111101;
}
void i2c_start( void )
{
SIGNAL_HIGH( PORT_SCL );
SIGNAL_HIGH( PORT_SDA );
SIGNAL_LOW( PORT_SDA );
SIGNAL_LOW( PORT_SCL );
}
void i2c_stop( void )
{
SIGNAL_LOW( PORT_SCL );
SIGNAL_LOW( PORT_SDA );
SIGNAL_HIGH( PORT_SCL );
SIGNAL_HIGH( PORT_SDA );
}
void i2c_write(uint8_t byte)
{
uint8_t bit;
for ( bit = 0; bit < 0x08; bit++ )
{
if( ( byte << bit ) & 0x80 )
SIGNAL_HIGH( PORT_SDA );
else
SIGNAL_LOW( PORT_SDA );
SIGNAL_HIGH( PORT_SCL );
SIGNAL_LOW( PORT_SCL );
}
SIGNAL_HIGH( PORT_SDA );
SIGNAL_HIGH( PORT_SCL );
SIGNAL_LOW( PORT_SCL );
}
I'm able to successfully write to I2C without any problems. I have tested this code with SSD1306 and LC2404B and everything works great even the timing if VCC is set to 4.2V.
i2c_init();
i2c_start();
i2c_write( 0xA0 );
i2c_write( 0x01 );
i2c_write( 0x13 );
i2c_stop();
While writting works perfectly, I can't seem to be able to trigger any of my I2C modules with ATTINY85 to return me a value that I can read later.
I connected raspberry and GY-521 sensor (since it returns value even if internal address is not set). I can detect the sensor and read a value from it with raspberry the following way:
i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
i2cget -y 1 0x68
0x02
This is the output on the oscilloscope:
I can see the sensor data changing. The problem is I can't seem to replicate the same request from ATTINY85 to the sensor. The sensor simply doesn't respond with the value.
I can't seem to understand if the last bit in the first byte is an ACK or 'READ' indicator bit, so I tried different addresses.
i2c_start();
i2c_write( 0b11010001 ); // address: 0xD1
i2c_start();
i2c_write( 0b11010000 ); // address: 0xD0
i2c_start();
i2c_write( 0b10100001 ); // address: 0xA1
i2c_start();
i2c_write( 0b10100000 ); // address: 0xA0
but regardless on what address I use, the sensor simply doesn't respond (in the oscioloscope) and the SDA line stays high after I send the address byte. I also tried to append another start() condition after I sent the address, but still no luck. Any hints on where I'm going wrong? I simply want to make the sensor respond to the ATTINY85 read request so I can later read the value. Thanks!
I'd suggest reading a couple tutorials on I2C to get a general understanding of the protocol. See https://learn.sparkfun.com/tutorials/i2c for example.
In short, I2C is a two-wire multi-master bus with a clock line and a data line. In any communication, whether it is a read or a write, the master supplies the clock signal. Your i2c_write() implements this with the SCL transitions.
In order to read a value back, you need to also supply the clock for that the slave uses to output data. No clock, no data. So, you need to implement an i2c_read() similar to your i2c write, that generates the clock transitions, and shifts in each bit one at a time.
You need to let the SDA line be an input so you can detect whether the slave is sending an ACK or not. You don't have any code to set the SDA line to be an input so there is no way the slave device could send any data back to you; the value you are putting on the SDA line might overpower whatever the slave is trying to do. And to read data back, you need to make an i2c_read function that wiggles the SCL line while SDA is an input. Your I2C implementation is therefore far from complete. You could carefully read the I2C spec from NXP or look for a more complete bit-banging I2C implementation to use as a reference.
Is there a difference between the two?
I have just changed from if(rdy) to if(rdy == 1) in some code for a project, and suddenly the output behaves totally different.
Assumes rdy is a 1-bit reg datatype in Verilog.
reg rdy;
if (rdy) <---> if (rdy!=1'b0)
if (rdy==1) <---> if (rdy==1'b1)
For synthesis, they will probably work the same. But be aware if rdy has more than 1 bit:
reg[7:0] rdy;
if (rdy) <---> if (rdy!=8'b00000000)
if (rdy==1) <---> if (rdy==8'b00000001)
The first one will probably be synthetized using an 8-input OR gate, while the second one will need a 7-input NOR gate and a 2-input AND gate.
There is no difference between the two.
reg is 4-state: 0, 1, x, z. Only if rdy is 1 will the if condition be true; otherwise, it is false.
module tb;
reg rdy;
always #(rdy) begin
if (rdy) begin
$display($time, " rdy=%b if (rdy) TRUE", rdy);
end else begin
$display($time, " rdy=%b if (rdy) FALSE", rdy);
end
if (rdy==1) begin
$display($time, " rdy=%b if (rdy==1) TRUE", rdy);
end else begin
$display($time, " rdy=%b if (rdy==1) FALSE", rdy);
end
$display;
end
initial begin
#5 rdy = 1'b1;
#5 rdy = 1'bx;
#5 rdy = 1'bz;
#5 rdy = 1'b0;
end
endmodule
Outputs:
5 rdy=1 if (rdy) TRUE
5 rdy=1 if (rdy==1) TRUE
10 rdy=x if (rdy) FALSE
10 rdy=x if (rdy==1) FALSE
15 rdy=z if (rdy) FALSE
15 rdy=z if (rdy==1) FALSE
20 rdy=0 if (rdy) FALSE
20 rdy=0 if (rdy==1) FALSE