Forum: FPGA, VHDL & Co. FlipFlop initial value bei MachXO2?


von KaffeKocher (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin Anfänger und habe mich an einem UART versucht. Das hat auch 
soweit geklappt, nun wollte ich einen Ausgang einbauen, der informieren 
soll, ob das Schieberegister leer ist und die nächste Übertragung 
starten kann. Dazu habe ich ein Signal im UART angelegt (tx_empty), dass 
ein FlipFlop sein soll, den Ausgang davon herausgeführt und dieses 
Signal mit High initialisiert (Startzustand ist '1'). Jetzt passiert 
aber nichts mehr, die TopLevel Entity startet keine Übertragung mehr. Es 
scheint, dass tx_empty von Anfang an low ist.

uart.vhdl
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
entity uart is
6
  generic (DATA_WIDTH: natural := 8; BAUDRATE: natural := 9600; CLOCKFREQ: natural := 1000000);
7
  port (
8
    clk: in std_logic;
9
    tx_data: in std_logic_vector(DATA_WIDTH-1 downto 0);
10
    tx_we: in std_logic;
11
    tx: out std_logic;
12
    tx_empty: out std_logic
13
  );
14
end uart;
15
16
architecture impl of uart is
17
  type state_t is (STATE_START, STATE_DATA, STATE_END);
18
  
19
  constant COUNTER_MAX: natural := CLOCKFREQ / BAUDRATE - 1;
20
  
21
  signal clk_counter: integer range 0 to COUNTER_MAX := 0;
22
  signal bit_counter: integer range 0 to DATA_WIDTH := 0;
23
  signal shift_register: std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
24
  signal state: state_t := STATE_START;
25
  signal tx_out: std_logic := '1';
26
  signal tx_empty_out: std_logic := '1';
27
begin
28
  tx <= tx_out;
29
  tx_empty <= tx_empty_out;
30
  
31
  process
32
  begin
33
    wait until rising_edge(clk);
34
    
35
    if state = STATE_START then
36
      if tx_we = '1' then
37
        tx_out <= '0';
38
      
39
        shift_register <= tx_data;
40
        
41
        tx_empty_out <= '0';
42
        
43
        clk_counter <= 0;
44
        bit_counter <= 0;
45
        
46
        state <= STATE_DATA;
47
      end if;
48
    elsif state = STATE_DATA then
49
      if clk_counter = COUNTER_MAX then
50
        clk_counter <= 0;
51
        
52
        if bit_counter = DATA_WIDTH then
53
          tx_out <= '1';
54
          state <= STATE_END;
55
        else
56
          tx_out <= shift_register(0);
57
          shift_register <= std_logic_vector(shift_right(unsigned(shift_register), 1));
58
          
59
          bit_counter <= bit_counter + 1;
60
        end if;
61
      else
62
        clk_counter <= clk_counter + 1;
63
      end if;
64
    else -- state = STATE_END
65
      if clk_counter = COUNTER_MAX then
66
        tx_empty_out <= '1';
67
        state <= STATE_START;
68
      else
69
        clk_counter <= clk_counter + 1;
70
      end if;
71
    end if;
72
  end process;
73
end impl;

toplevel.vhdl
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
5
library work;
6
  use work.all;
7
  
8
entity test is
9
  port (tx: out std_logic; tx_empty_out: out std_logic);
10
end test;
11
12
architecture impl of test is
13
  signal clk: std_logic;
14
  signal tx_we: std_logic := '0';
15
  signal tx_empty: std_logic;
16
begin
17
  osc0: entity oscillator port map (clk => clk);
18
  uart0: entity uart generic map (DATA_WIDTH => 8, BAUDRATE => 9600, CLOCKFREQ => 2080000)
19
             port map (clk => clk, tx_data => "10100011", tx_we => tx_we, tx => tx, tx_empty => tx_empty);
20
             
21
  tx_empty_out <= tx_empty;
22
  
23
  process
24
  begin
25
    wait until rising_edge(clk);
26
    
27
    if tx_empty = '1' then
28
      tx_we <= '1';
29
    else
30
      tx_we <= '0';
31
    end if;
32
  end process;
33
end impl;

Danach habe ich die Bedingung in toplevel.vhdl rausgelassen und tx_we 
konstant auf '1' belassen, nun funktionierts. Ein Blick mit dem 
LogicAnalyzer bestätigt die Vermutung, dass tx_empty nicht den richtigen 
Startzustand hat. Aber warum? Aus tx_empty wird ein FlipFlop, das 
bestätigt auch die Netzliste. Oder werden non-zero initial ff values von 
MachXO2 gar nicht unterstützt? Ignoriert der Synthesizer den initialen 
Wert bei der Deklaration des Signals? Ich bin leider kein deut schlauer 
aus meiner Internetrecherche geworden, nur dass das nicht von allen 
FPGAs unterstützt wird. Achja ich nutze Lattice LSE zur Synthese. Bilder 
sind im Anhang.

Vielen Dank.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

KaffeKocher schrieb:
>  dass das nicht von allen FPGAs unterstützt wird
Es ist hier (abgesehen von Actels Antifuse FPGAs) eher die Toolchain, 
die Initwerte nicht unterstützt. Funktioniert es denn, wenn du die Logik 
invertierst (also 0=Frei)?

von KaffeKocher (Gast)


Angehängte Dateien:

Lesenswert?

Tatsächlich, beim invertierten Ausgang läuft er durch.
Also scheint es Lattice LSE nicht mitzumachen. Hab aber nichts in den 
Datenblättern gefunden, nur dass im HDL User Guide kein Gebrauch von 
Initialwerten gemacht wird.

von KaffeKocher (Gast)


Lesenswert?

Jap habs nun ordentlich geändert nicht nur invertiert, gleiches 
Ergebnis. So läuft es jedenfalls. Der Startwert von tx ist allerdings 
auch nicht High sondern leider low. Die Toolchain ignoriert es einfach, 
leider nur ohne Warnung...

Aber warum sollte man so ein Feature nicht unterstützen, wo es doch der 
FPGA extra kann und es doch sehr nützlich ist? Vor allem toll, wenn man 
Unmengen an Komponenten hat, die ohne gar nicht funktionieren.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

KaffeKocher schrieb:
> Aber warum sollte man so ein Feature nicht unterstützen, wo es doch der
> FPGA extra kann
Welchen Synthesizer verwendest du?

von KaffeKocher (Gast)


Lesenswert?


von Duke Scarring (Gast)


Lesenswert?

KaffeKocher schrieb:
> Lattice LSE in Diamond IDE (3.8)
Test mal mit Synplify, das sollte doch auch dabei sein.

Duke

von KaffeKocher (Gast)


Lesenswert?

Leider nur auf Windows, aber ich probiers trotzdem.

von Charles G. (Firma: Ingenieurbuero Gardiner) (cfgardiner)


Lesenswert?

Meines Wissens unterstützen keine Synopsys Synthese Tools VHDL 
Initialwerte. Es muesste auch in den tausend Log Meldungen irgendwo so 
etwas stehen wie
"Warning: Initial values are not supported for synthesis"

Ob Initialwerte von den anderen Synthesetools unterstützt werden weiß 
ich nicht auswendig, portable im Sinne des "VHDL synthesisable subsets" 
ist es halt nicht.

Was du brauchst ist ein Reset Signal, egal ob synchron oder asynchron.

Es gibt natürlich auch andere Lösungen, z.B. einen Memory mit 
vordefinierten Inhalt definieren mit nur einem Bit, der beim loslaufen 
des Taktes seinen Inhalt invertiert, aber solche Lösungen sind meistens 
größer und umständlicher als ein einfacher Reset.

von Duke Scarring (Gast)


Lesenswert?

Charles G. schrieb:
> Meines Wissens unterstützen keine Synopsys Synthese Tools VHDL
> Initialwerte
Das kann sein. Allerdings haben alle meine MachXO2-Designs keinen 
Reset und nutzen - teils intensiv - Initialwerte a la:
1
    signal config_array : config_array_t := default_config_array;
2
...
3
    constant config_c : config_type := (
4
        0      => to_slv( ident_gpio),
5
        1      => to_slv( no_reponse, 0),
6
        2      => std_ulogic_vector( to_unsigned( 8, 8)),
7
        others => default_slv8
8
    );
9
...
10
    config_array( 21) <= config_c;

Mir ist das bisher nur bei Altera Quartus und da speziell beim Debugging 
auf die Füsse gefallen:
Dort wird (ohne Meldung) die Logik invertiert, wenn der Initialwert 
gleich eins ist. Dann sehen die FSM-States und Flags im Debugger anders 
aus, als im Simulator...

Duke

von KaffeKocher (Gast)


Angehängte Dateien:

Lesenswert?

Also mit Synplify Pro tut es wie vorgesehen, tx und tx_empty sind bei 
t_0 high (siehe Bild).

Charles G. schrieb:
> Meines Wissens unterstützen keine Synopsys Synthese Tools VHDL
> Initialwerte. Es muesste auch in den tausend Log Meldungen irgendwo so
> etwas stehen wie
> "Warning: Initial values are not supported for synthesis"

Die gibt es auch, aber nur für das Schieberegister. Da hat er aber 
recht.
1
GSR will not be inferred because no asynchronous signal was found in the netlist.
2
WARNING - synthesis: Initial value found on instance \uart0/shift_register_i0_i0 will be ignored.
3
WARNING - synthesis: Initial value found on instance \uart0/shift_register_i0_i5 will be ignored.
4
WARNING - synthesis: Initial value found on instance \uart0/shift_register_i0_i1 will be ignored.
5
Applying 1.000000 MHz constraint to all clocks

Log ist im Anhang.

von Charles G. (Firma: Ingenieurbuero Gardiner) (cfgardiner)


Lesenswert?

Entschuldige, aber das was du beschreibst ist gar kein Initialwert. Hier 
definierst du einen Constanten. Zuweisen tust du es erst später mit der 
Zeile
    config_array( 21) <= config_c;

Die Zuweisung ist vermutlich in einem Process oder ähnlich.

Bei der definition eines Constants muessen alle Elemente spezifiziert, 
sonst wäre es logischerweise kein Constant. Es ist nicht ganz das 
gleiche als was der OP machen will.

Was er machen will, ist schon bei einer signal Definition ein Initalwert 
zuweisen. DAS geht nicht. Ein FPGA/ASIC ist nun mal Ereignis gesteuert. 
Entweder ein Takt oder ein sonstiges Signal muss etwas auslösen. Als 
sonstiges gilt z.B. ein Reset Eingang. Woher soll das Synthese Tool 
sonst wissen welches Ereignis ein "lade InitialWert" auslösen soll? 
"FPGA Image von SPI laden fertig" ist dem Synthese Tool als Ereignis 
einfach nicht bekannt. Beim ASIC gibt es das sowieso nicht und die 
Synthese sollte hier agnostisch sein.

Der Zustand eines generischen FPGAs/ASICs unmittelbar nach dem Power-On, 
Lade-von-SPI etc. ist nun mal undefiniert. Dass bei den meisten FPGAs 
alle Flipflops den Wert '0' annehemen ist höchstens technologie bzw. 
herstellerbedingt. Annehemen kann (oder zumindest sollte) man es nicht.

Ausserdem, wenn du keinen sauberen Reset hast, kannst du nie und nimmer 
alles in einem definierten Zustand bringen ohne Power Cycle.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Charles G. schrieb:
> Was er machen will, ist schon bei einer signal Definition ein Initalwert
> zuweisen. DAS geht nicht.
Xilinx unterstützt Initialwerte schon seit geraumer Zeit (ISE 11 oder 
so). Und propagiert das komplette Weglassen des Resets z.B. im WP272.

> Dass bei den meisten FPGAs alle Flipflops den Wert '0' annehemen ist
> höchstens technologie bzw. herstellerbedingt. Annehemen kann (oder
> zumindest sollte) man es nicht.
Ja, man muss da offenbar noch immer den Synthesizer Users Guide in die 
Hand nehmen. Z.B. den auf Seite 69 unten:
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_1/ug901-vivado-synthesis.pdf

> Woher soll das Synthese Tool sonst wissen welches Ereignis ein "lade
> InitialWert" auslösen soll?
Der INIT-Pin am FPGA startet das Neuladen. Dorthin gehört der 
Reset-Taster. Und beim Laden wird in jedem SRAM-basierten FPGA sowieso 
jedes Flipflop "angefasst" und in einen definierten Zustand gebracht. 
Es ist also nur ein Problem der Toolchain (bis hin zum 
Bitstromgenerator), wenn sie es nicht kann.

KaffeKocher schrieb:
> Also mit Synplify Pro tut es wie vorgesehen, tx und tx_empty sind bei
> t_0 high (siehe Bild).
So kenne ich das auch, deshalb meine Frage nach dem Synthesizer. 
Allerdings meinte ich, dass die Lattice-Synthese das auch mal konnte. 
Arg neu ist die Technik ja nun nicht gerade. Immerhin haben wir das vor 
ewiger Zeit im Beitrag "Xilinx und die Resets" schon 
diskutiert...

von KaffeKocher (Gast)


Lesenswert?

Lothar M. schrieb:
>> Woher soll das Synthese Tool sonst wissen welches Ereignis ein "lade
>> InitialWert" auslösen soll?
> Der INIT-Pin am FPGA startet das Neuladen. Dorthin gehört der
> Reset-Taster. Und beim Laden wird in jedem SRAM-basierten FPGA sowieso
> jedes Flipflop "angefasst" und in einen definierten Zustand gebracht.
> Es ist also nur ein Problem der Toolchain (bis hin zum
> Bitstromgenerator), wenn sie es nicht kann.

Ja so hab ich das auch verstanden und wollte mir jegliche Resetlogik 
sparen um weniger Ressourcen zu verbraten.

Im "Lattice Synthesis Engine for Diamond User Guide" kann ich leider 
nichts entdecken, außer dass BlockRAM so initialisiert werden kann, aber 
nichts über FlipFlops.

Zumindest hab ich schon mal die Info, dass alle Register genullt werden.
1
Are the registers in MachXO2 initialized to a known value after a re-configuration operation?
2
3
In MachXO2, during normal device power-up, all registers are initialized to zero.  The same is true for re-configuration operations.

http://www.latticesemi.com/en/Support/AnswerDatabase/2/6/6/2665.aspx

Vielleicht finde ich noch was...

von Charles G. (Firma: Ingenieurbuero Gardiner) (cfgardiner)


Lesenswert?

KaffeKocher schrieb:
> Lothar M. schrieb:
>>> Woher soll das Synthese Tool sonst wissen welches Ereignis ein "lade
>>> InitialWert" auslösen soll?
>> Der INIT-Pin am FPGA startet das Neuladen. Dorthin gehört der
>> Reset-Taster. Und beim Laden wird in jedem SRAM-basierten FPGA sowieso
>> jedes Flipflop "angefasst" und in einen definierten Zustand gebracht.
>> Es ist also nur ein Problem der Toolchain (bis hin zum
>> Bitstromgenerator), wenn sie es nicht kann.
>
> Ja so hab ich das auch verstanden und wollte mir jegliche Resetlogik
> sparen um weniger Ressourcen zu verbraten.

Und wenn ich z.B. eine PC Steckkarte habe und ein Warm-Start machen 
will, soll dann auch jedes Mal das FPGA Image neu geladen werden nur um 
alles in einen definierten Zustand zu bringen? Da ist doch ein globales 
Reset Netz (GSR bei Lattice) deutlich einfacher (und schneller).

Wenn ich für Lattice entwickele interessiere ich mich auch nicht 
besonders dafür wie es Xilinx machen würde.

Die Synthese-Tool Hersteller haben in der Regel eher nach IEEE 1076.6 
"Standard for VHDL Register Transfer Level Synthesis" entwickelt und das 
ist nun mal eine Untermenge vom vollen VHDL Standard. Wenn man sein Code 
portabel (und nicht nur für Xilinx) schreiben will, gibt es halt gewisse 
Einschränkungen, mit denen man aber durchaus gut leben kann.

Und falls du dich mal von deinem Xilinx Biotop erfolgreich freigekämpft 
hast, wirdst du feststellen, dass so gut wie alle OEM EDA Tools ganz gut 
mit einer erprobten "Best Practice" zu bedienen sind.

>
> Im "Lattice Synthesis Engine for Diamond User Guide" kann ich leider
> nichts entdecken, außer dass BlockRAM so initialisiert werden kann, aber
> nichts über FlipFlops.

Wennn du deinen Baustein eine Reset Eingang spendierst und in allen 
Process Blöcken einen Reset Pfad einbaust, werden alle Flipflops 
automatisch mit dem GSR Netz verbunden. Je nachdem, ob der Reset Code 
einen Flipflop auf '0' oder '1' setzt wird GSR mit dem Set oder Reset 
Eingang verbunden.

Das globale GSR Netz wird dann von deinem Reset Pin angesteuert.

>
> Zumindest hab ich schon mal die Info, dass alle Register genullt werden.
>
1
> Are the registers in MachXO2 initialized to a known value after a 
2
> re-configuration operation?
3
> 
4
> In MachXO2, during normal device power-up, all registers are initialized 
5
> to zero.  The same is true for re-configuration operations.
6
>
>
> http://www.latticesemi.com/en/Support/AnswerDatabase/2/6/6/2665.aspx
>
> Vielleicht finde ich noch was...

von KaffeKocher (Gast)


Lesenswert?

Verstehe, d.h. der GSR wäre auch der portable Weg und der GSR wird 
sowieso genutzt um die Register zu initialisieren.

Den GSR darf nach Lattice nur als asynchronen Reset genutzt werden, 
schaltet der FPGA dann auch die Taktquellen aus, damit nichts schief 
gehen kann?

Habe nun eine Resetleitung hinzugefügt (GSR instantiiert und mit "rst" 
Signal verbunden). Jetzt beschwert sich der Synthesizer:
1
using initial value 'U' for rst since it is never assigned. VHDL-1303

Und behauptet, dass sich die ganzen Register in der UART Komponente nie 
ändern...
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
library machxo2;
6
  use machxo2.all;
7
  use machxo2.components.all;
8
9
library work;
10
  use work.all;
11
  
12
entity test is
13
  port (tx: out std_logic; tx_empty_out: out std_logic);
14
end test;
15
16
architecture impl of test is
17
  signal clk: std_logic;
18
  signal rst: std_logic;
19
  signal tx_we: std_logic;
20
  signal tx_empty: std_logic;
21
begin
22
  gsr0: GSR port map (gsr => rst);
23
  osc0: entity oscillator port map (clk => clk);
24
  uart0: entity uart generic map (DATA_WIDTH => 8, BAUDRATE => 9600, CLOCKFREQ => 2080000)
25
             port map (clk => clk, rst => rst, tx_data => "10100011", tx_we => tx_we, tx => tx, tx_empty => tx_empty);
26
             
27
  tx_empty_out <= tx_empty;
28
  
29
  process
30
  begin
31
    wait until rising_edge(clk);
32
    
33
    if tx_empty = '1' then
34
      tx_we <= '1';
35
    else
36
      tx_we <= '0';
37
    end if;
38
  end process;
39
end impl;

Muss ich den GSR mit einem Inputpin verbinden? So wie bei diesem 
Beispiel? Davon habe ich bisher aber nichts gelesen.
https://github.com/bugblat/pif/blob/master/firmware/common/flashctl.vhd

von KaffeKocher (Gast)


Lesenswert?

1
To use the Global GSR usage case, a GSR component must be instantiated
2
in the design and connected to the signal that is targeted as the reset signal,
3
usually a primary input.

Ok, so wie ich das verstehe, muss das Netz noch zusätzlich mit einer 
Signalquelle verbunden werden.
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
library machxo2;
6
  use machxo2.all;
7
  use machxo2.components.all;
8
9
library work;
10
  use work.all;
11
  
12
entity test is
13
  port (tx: out std_logic; tx_empty_out: out std_logic);
14
end test;
15
16
architecture impl of test is
17
  signal clk: std_logic;
18
  signal rst: std_logic;
19
  signal tx_we: std_logic;
20
  signal tx_empty: std_logic;
21
  
22
  attribute pullmode  : string;
23
  attribute pullmode of rst: signal is "UP";   -- else floats
24
begin
25
  gsr0: GSR port map (gsr => rst);
26
  osc0: entity oscillator port map (clk => clk);
27
  uart0: entity uart generic map (DATA_WIDTH => 8, BAUDRATE => 9600, CLOCKFREQ => 2080000)
28
             port map (clk => clk, rst => rst, tx_data => "10100011", tx_we => tx_we, tx => tx, tx_empty => tx_empty);
29
             
30
  tx_empty_out <= tx_empty;
31
  rst <= '1';
32
  
33
  process
34
  begin
35
    wait until rising_edge(clk);
36
    
37
    if tx_empty = '1' then
38
      tx_we <= '1';
39
    else
40
      tx_we <= '0';
41
    end if;
42
  end process;
43
end impl;

Jetzt sind die Warnungen zwar weg, aber es läuft leider noch nicht. Mach 
ich was beim UART Reset noch falsch?
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
entity uart is
6
  generic (DATA_WIDTH: natural := 8; BAUDRATE: natural := 9600; CLOCKFREQ: natural := 1000000);
7
  port (
8
    clk: in std_logic;
9
    rst: in std_logic;
10
    tx_data: in std_logic_vector(DATA_WIDTH-1 downto 0);
11
    tx_we: in std_logic;
12
    tx: out std_logic;
13
    tx_empty: out std_logic
14
  );
15
end uart;
16
17
architecture impl of uart is
18
  type state_t is (STATE_START, STATE_DATA, STATE_END);
19
  
20
  constant COUNTER_MAX: natural := CLOCKFREQ / BAUDRATE - 1;
21
  
22
  signal clk_counter: integer range 0 to COUNTER_MAX := 0;
23
  signal bit_counter: integer range 0 to DATA_WIDTH := 0;
24
  signal shift_register: std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
25
  signal state: state_t := STATE_START;
26
  signal tx_out: std_logic := '1';
27
  signal tx_empty_out: std_logic := '1';
28
begin
29
  tx <= tx_out;
30
  tx_empty <= tx_empty_out;
31
  
32
  process (clk, rst)
33
  begin
34
    --wait until rising_edge(clk);
35
    if rising_edge(clk) then
36
    
37
      if state = STATE_START then
38
        if tx_we = '1' then
39
          tx_out <= '0';
40
        
41
          shift_register <= tx_data;
42
          
43
          tx_empty_out <= '0';
44
          
45
          clk_counter <= 0;
46
          bit_counter <= 0;
47
          
48
          state <= STATE_DATA;
49
        end if;
50
      elsif state = STATE_DATA then
51
        if clk_counter = COUNTER_MAX then
52
          clk_counter <= 0;
53
          
54
          if bit_counter = DATA_WIDTH then
55
            tx_out <= '1';
56
            state <= STATE_END;
57
          else
58
            tx_out <= shift_register(0);
59
            shift_register <= std_logic_vector(shift_right(unsigned(shift_register), 1));
60
            
61
            bit_counter <= bit_counter + 1;
62
          end if;
63
        else
64
          clk_counter <= clk_counter + 1;
65
        end if;
66
      else -- state = STATE_END
67
        if clk_counter = COUNTER_MAX then
68
          tx_empty_out <= '1';
69
          state <= STATE_START;
70
        else
71
          clk_counter <= clk_counter + 1;
72
        end if;
73
      end if;
74
    end if;
75
    
76
    if rst = '0' then
77
      clk_counter <= 0;
78
      bit_counter <= 0;
79
      shift_register <= (others => '0');
80
      state <= STATE_START;
81
      tx_out <= '1';
82
      tx_empty_out <= '1';
83
    end if;
84
  end process;
85
end impl;

von Charles G. (Firma: Ingenieurbuero Gardiner) (cfgardiner)


Lesenswert?

KaffeKocher schrieb:
> Verstehe, d.h. der GSR wäre auch der portable Weg und der GSR wird
> sowieso genutzt um die Register zu initialisieren.

Im prinzip ja. Auf dem Lattice Silizium gibt es ein globales Netz (GSR), 
das an jeden Flipflop geführt wird, ähnlich wie ein Taktnetz. 
Typischerweise wird das als asynchroner Reset verwendet. Sofern Resets 
verwendet werden, tut die Synthese das Reset mit dem höchsten Fanout dem 
GSR Netz zuordnen. Ob das Netz mit dem Set oder Reset Eingang eines 
bestimmten Flipflops verbunden wird hängt von deinem VHDL code ab.

z.B. im folgenden Snippit wird der CLR Eingang vom Flipflop s_sig_1 
sowie der SET Eingang vom s_sig_2 mit i_rst_n verbunden  und über das 
GSR Netz geroutet. GSR wird zusätzlich mit dem Treiber vom i_rst_n Netz 
verbunden. Sinnvollerweise entweder ein physikalischer Baustein Pin oder 
eine interne Reset Statemaschine.

Process (i_clk, i_rst_n)
Begin
   if (i_rst_n = '0') then
      s_sig1  <= '0';
      s_sig_2 <= '1';
   elsif (rising_edge(i_clk)) then
      -- Functional code goes here
   end if;
End Process;


>
> Den GSR darf nach Lattice nur als asynchronen Reset genutzt werden,
> schaltet der FPGA dann auch die Taktquellen aus, damit nichts schief
> gehen kann?

Da ist vielleicht die Beschreibung nicht ganz deutlich. Richtig ist, nur 
die asynchrone SET bzw. CLR Flipflop Eingänge können Empfänger des GSR 
Netzes sein. Quelle (Treiber) des GSR Netzes kann aber beliebig sein so 
z.B. ein physikalischer Pin oder ein Flipflop in einer Reset State 
Maschine.

>
> Habe nun eine Resetleitung hinzugefügt (GSR instantiiert und mit "rst"
> Signal verbunden). Jetzt beschwert sich der Synthesizer:
>
>
1
> using initial value 'U' for rst since it is never assigned. VHDL-1303
2
>
>
> Und behauptet, dass sich die ganzen Register in der UART Komponente nie
> ändern...
>
>
1
> library ieee;
2
>   use ieee.std_logic_1164.all;
3
>   use ieee.numeric_std.all;
4
> 
5
> library machxo2;
6
>   use machxo2.all;
7
>   use machxo2.components.all;
8
> 
9
> library work;
10
>   use work.all;
11
> 
12
> entity test is
13
>   port (tx: out std_logic; tx_empty_out: out std_logic);
14
> end test;
15
> 
16
> architecture impl of test is
17
>   signal clk: std_logic;
18
>   signal rst: std_logic;
19
>   signal tx_we: std_logic;
20
>   signal tx_empty: std_logic;
21
> begin
22
>   gsr0: GSR port map (gsr => rst);
23
>   osc0: entity oscillator port map (clk => clk);
24
>   uart0: entity uart generic map (DATA_WIDTH => 8, BAUDRATE => 9600, 
25
> CLOCKFREQ => 2080000)
26
>              port map (clk => clk, rst => rst, tx_data => "10100011", 
27
> tx_we => tx_we, tx => tx, tx_empty => tx_empty);
28
> 
29
>   tx_empty_out <= tx_empty;
30
> 
31
>   process
32
>   begin
33
>     wait until rising_edge(clk);
34
> 
35
>     if tx_empty = '1' then
36
>       tx_we <= '1';
37
>     else
38
>       tx_we <= '0';
39
>     end if;
40
>   end process;
41
> end impl;
42
>
>

Mein Rat wäre die alternativ Syntax zu verwenden.
 process (rst_n, clk)
 begin
 if (rst_n = '0') then
 elsif (rising_edge(clk)) then
 end if;
 end proces;

An deinem Entity muss natürlich das rst Signal an einen Pin oder Reset 
FSM geführt werden.

> Muss ich den GSR mit einem Inputpin verbinden? So wie bei diesem
> Beispiel? Davon habe ich bisher aber nichts gelesen.

Nein, nicht persönlich. Die Verwendung des GSR Netzes wird inferiert. 
Deine Schaltung könnte theoretisch mehrere Resets haben. Wie oben 
erwähnt, das asynchrone Reset Signal mit dem höchsten Fanout wird über 
das GSR Netz geführt.

Es steht dann auch eine Meldung in der Log Datei welches Netz 
tatsächlich verwendet wird. Ich glaube es gibt schon eine möglichkeit 
ein bestimmtes Netz an GSR zuzuweisen wenn man das GSR Primitiv in seine 
Schaltung selber instanziiert. Das GSR Primitiv ist eine Zelle mit nur 
einem Eingang (der Eingang/Treiber zum GSR Netz, sozusagen). Somit kann 
man die standard Syntheseauswahl überstimmen.


> https://github.com/bugblat/pif/blob/master/firmware/common/flashctl.vhd

von KaffeKocher (Gast)


Lesenswert?

Mit Resetpin/taster funktionierts ziemlich gut.
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
library machxo2;
6
  use machxo2.all;
7
  use machxo2.components.all;
8
9
library work;
10
  use work.all;
11
  
12
entity test is
13
  port (rst: in std_logic; tx: out std_logic; tx_empty_out: out std_logic);
14
end test;
15
16
architecture impl of test is
17
  signal clk: std_logic;
18
  signal tx_we: std_logic;
19
  signal tx_empty: std_logic;
20
  
21
  --attribute pullmode  : string;
22
  --attribute pullmode of rst: signal is "UP";   -- else floats
23
begin
24
  gsr0: GSR port map (gsr => rst);
25
  osc0: entity oscillator port map (clk => clk);
26
  uart0: entity uart generic map (DATA_WIDTH => 8, BAUDRATE => 9600, CLOCKFREQ => 2080000)
27
             port map (clk => clk, rst => rst, tx_data => "10100011", tx_we => tx_we, tx => tx, tx_empty => tx_empty);
28
             
29
  tx_empty_out <= tx_empty;
30
  
31
  process
32
  begin
33
    wait until rising_edge(clk);
34
    
35
    if tx_empty = '1' then
36
      tx_we <= '1';
37
    else
38
      tx_we <= '0';
39
    end if;
40
  end process;
41
end impl;

Die Frage ist, passt das so (außer dass im toplevel noch ein Reset 
fehlt)?

von Charles G. (Firma: Ingenieurbuero Gardiner) (cfgardiner)


Lesenswert?

Ich waage es zu bezweifeln, dass das funktioniert wie du willst.

Mit dieser Zeile
gsr0: GSR port map (gsr => rst);

hast du zwar ein Sender am GSR Netz aber ich erkenne nicht wie die 
Synthese die Empfänger erraten soll. Wie gesagt, GSR wird in Silizium zu 
jedem Flipflop geführt aber nicht zwingend mit jedem Flipflop verbunden. 
Ob es verbunden wird hängt davon ab, ob die Synthese eine asynchrone 
SET/CLR Aktion an einem Flipflop aus deinem HDL code erkennt. Es wäre 
mir neu, dass Synplify jetzt Empfänger aus dem Initialwert inferiert 
aber ich mache ja meine Reset Netze anders. Kann gut sein ich hab's nur 
nicht bemerkt.

Die synplify docu für Lattice steht unter 
C:\lscc\diamond\3.8_x64\synpbase\doc z.B. (mehrere PDFs) da muesste es 
eigentlich drin stehen, ob Initialwerte unterstützt werden.

Noch ein Punkt, der interne Oszillator is relativ ungenau
osc0: entity oscillator port map (clk => clk);

Die Frequenz ist letzendlich vom Fertigungslos abhängig (Streuung kann 
gut mal 30% sein). Zum Üben, für Loopback oder wenn zwei UARTs im selben 
MachXO sind wird es vermutlich funktionieren aber nicht z.B. mit einem 
externen Mikrocontroller, oder jedenfalls nicht immer. Dafür bräuchtest 
du eine externe Taktquelle.

: Bearbeitet durch User
von KaffeKocher (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab leider deinen Beitrag übersehen, du hast deinen kurz vor meinem 
abgesendet.

Also nun der aktuelle Stand.

toplevel.vhdl
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
library machxo2;
6
  use machxo2.all;
7
  use machxo2.components.all;
8
9
library work;
10
  use work.all;
11
  
12
entity test is
13
  port (rst: in std_logic; tx: out std_logic; tx_empty_out: out std_logic);
14
end test;
15
16
architecture impl of test is
17
  signal clk: std_logic;
18
  signal tx_we: std_logic;
19
  signal tx_empty: std_logic;
20
begin
21
  gsr0: GSR port map (gsr => rst);
22
  osc0: entity oscillator port map (clk => clk);
23
  uart0: entity uart generic map (DATA_WIDTH => 8, BAUDRATE => 9600, CLOCKFREQ => 2080000)
24
             port map (clk => clk, rst => rst, tx_data => "10100011", tx_we => tx_we, tx => tx, tx_empty => tx_empty);
25
             
26
  tx_empty_out <= tx_empty;
27
  
28
  process (clk, rst)
29
  begin
30
    if rst = '0' then
31
      tx_we <= '0';
32
    elsif rising_edge(clk) then
33
      if tx_empty = '1' then
34
        tx_we <= '1';
35
      else
36
        tx_we <= '0';
37
      end if;
38
    end if;
39
  end process;
40
end impl;

uart.vhdl
1
library ieee;
2
  use ieee.std_logic_1164.all;
3
  use ieee.numeric_std.all;
4
  
5
entity uart is
6
  generic (DATA_WIDTH: natural := 8; BAUDRATE: natural := 9600; CLOCKFREQ: natural := 1000000);
7
  port (
8
    clk: in std_logic;
9
    rst: in std_logic;
10
    tx_data: in std_logic_vector(DATA_WIDTH-1 downto 0);
11
    tx_we: in std_logic;
12
    tx: out std_logic;
13
    tx_empty: out std_logic
14
  );
15
end uart;
16
17
architecture impl of uart is
18
  type state_t is (STATE_START, STATE_DATA, STATE_END);
19
  
20
  constant COUNTER_MAX: natural := CLOCKFREQ / BAUDRATE - 1;
21
  
22
  signal clk_counter: integer range 0 to COUNTER_MAX;
23
  signal bit_counter: integer range 0 to DATA_WIDTH;
24
  signal shift_register: std_logic_vector(DATA_WIDTH-1 downto 0);
25
  signal state: state_t;
26
  signal tx_out: std_logic;
27
  signal tx_empty_out: std_logic;
28
begin
29
  tx <= tx_out;
30
  tx_empty <= tx_empty_out;
31
  
32
  process (clk, rst)
33
  begin
34
    if rst = '0' then
35
      clk_counter <= 0;
36
      bit_counter <= 0;
37
      shift_register <= (others => '0');
38
      state <= STATE_START;
39
      tx_out <= '1';
40
      tx_empty_out <= '1';
41
    elsif rising_edge(clk) then
42
      if state = STATE_START then
43
        if tx_we = '1' then
44
          tx_out <= '0';
45
        
46
          shift_register <= tx_data;
47
          
48
          tx_empty_out <= '0';
49
          
50
          clk_counter <= 0;
51
          bit_counter <= 0;
52
          
53
          state <= STATE_DATA;
54
        end if;
55
      elsif state = STATE_DATA then
56
        if clk_counter = COUNTER_MAX then
57
          clk_counter <= 0;
58
          
59
          if bit_counter = DATA_WIDTH then
60
            tx_out <= '1';
61
            state <= STATE_END;
62
          else
63
            tx_out <= shift_register(0);
64
            shift_register <= std_logic_vector(shift_right(unsigned(shift_register), 1));
65
            
66
            bit_counter <= bit_counter + 1;
67
          end if;
68
        else
69
          clk_counter <= clk_counter + 1;
70
        end if;
71
      else -- state = STATE_END
72
        if clk_counter = COUNTER_MAX then
73
          tx_empty_out <= '1';
74
          state <= STATE_START;
75
        else
76
          clk_counter <= clk_counter + 1;
77
        end if;
78
      end if;
79
    end if;
80
  end process;
81
end impl;

Die Netzliste sieht jetzt auch wesentlich besser aus. Set bzw. Reset 
sind nun mit dem GSR und dem Resetpin verbunden. Toplevel ist oben zu 
sehen, die Netzliste von UART ist ein bisschen zu groß geworden für ein 
Bild.

Charles G. schrieb:
> Die synplify docu für Lattice steht unter
> C:\lscc\diamond\3.8_x64\synpbase\doc z.B. (mehrere PDFs) da muesste es
> eigentlich drin stehen, ob Initialwerte unterstützt werden.

Ich schau eventuell noch mal nach, aber die GSR Lösung gefällt mir 
eigentlich recht gut.

Charles G. schrieb:
> Noch ein Punkt, der interne Oszillator is relativ ungenau
> osc0: entity oscillator port map (clk => clk);
>
> Die Frequenz ist letzendlich vom Fertigungslos abhängig (Streuung kann
> gut mal 30% sein). Zum Üben, für Loopback oder wenn zwei UARTs im selben
> MachXO sind wird es vermutlich funktionieren aber nicht z.B. mit einem
> externen Mikrocontroller, oder jedenfalls nicht immer. Dafür bräuchtest
> du eine externe Taktquelle.

Ja hab ich mir schon gedacht, war aber erst mal nur zum Üben. Ich nutze 
das MachXO2 Pico Board, da hat der FPGA leider keinen Quarz, wobei man 
höchstwahrscheinlich den Quarz vom FTDI IC auch nutzen kann. War bisher 
nur zu faul um nachzuschauen :)

Auf jeden Fall schon mal vielen Dank an alle!

von Holger (Gast)


Lesenswert?

KaffeKocher schrieb:
> Ja hab ich mir schon gedacht, war aber erst mal nur zum Üben. Ich nutze
> das MachXO2 Pico Board, da hat der FPGA leider keinen Quarz, wobei man
> höchstwahrscheinlich den Quarz vom FTDI IC auch nutzen kann. War bisher
> nur zu faul um nachzuschauen :)
###################################
Pico Board habe ich auch, klasse Teil.
Ja klar geht das, hast du den Stromlaufplan von dem Pico Board.

Hast du schon mal versucht den Source Code von dem RefDesign des Pico 
Boards zu kompilen. Ich bekomme den für das Pico Board nicht gefittet, 
da der Speicher zu klein ist Typ 1200... . Somit ist das Lattice 
Ref.Design für das PicoBoard eigentlich zum Üben wertlos. So ein Mist 
aber auch.
Nur den orginal Refdesign BitFile kann ich da reinflaschen. Was denken 
die sich bei Lattice da nun dabei.

Gruss Holger.

von C. A. Rotwang (Gast)


Lesenswert?

Lothar M. schrieb:

> Xilinx unterstützt Initialwerte schon seit geraumer Zeit (ISE 11 oder
> so). Und propagiert das komplette Weglassen des Resets z.B. im WP272.

Nein, vom kompletten Weglassen des resets steht nix in dem White Paper.


Da steht das man sich das globale Resetnetzwerk sparen kann, wenn man 
nur einzelne FF in den Reset schickt, also lokal. Synchronizer FF in den 
reset zwingen ist unnötig, bei FSM mag das anders aussehen. Deshalb ist 
das White Paper auch mit "Think Local, not Global" betitelt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

C. A. Rotwang schrieb:
> Nein, vom kompletten Weglassen des resets steht nix in dem White Paper.
Es wird in diesem WP viel grundlegender gefragt, ob ein globaler Reset 
(Resetpin/Resettaster) überhaupt nötig ist. Und i.A. lautet die Antwort 
darauf: Nein!
1
Summary
2
A design implemented in a Xilinx FPGA does not require insertion of a global reset network.

Charles G. schrieb:
> Da ist vielleicht die Beschreibung nicht ganz deutlich. Richtig ist, nur
> die asynchrone SET bzw. CLR Flipflop Eingänge können Empfänger des GSR
> Netzes sein. Quelle (Treiber) des GSR Netzes kann aber beliebig sein so
> z.B. ein physikalischer Pin oder ein Flipflop in einer Reset State
> Maschine.
Und das ist es dann auch, was Altera analog zu Lattice empfiehlt: den 
Reseteingang nicht direkt auf einen Eingangspin, sondern erst mal in 
die jeweilige Taktdomäne eintakten, damit der Reset eben tatsächlich 
synchron inaktiv(!) wird.
Zu einem komplett asynchronen Reset sagt z.B. der Altera DRC folgendes:
1
Warning: (Medium) Rule R102: External reset signals should be synchronized using two cascaded registers.
... und zwar getaktet von der jeweiligen Taktdomäne der betroffenen 
Flipflops.

Und das ist der Knackpunkt: es gibt 1 einziges GSR Netz, dann geht das 
Einsynchronisieren auf 1 Takt problemlos. Lustig und interessant wird 
es, sobald eine zweite (unabhängige) Taktdomäne im FPGA werkelt. Denn 
die bräuchte zum synchronen Deaktivieren des Resets ja "ihr eigenes GSR" 
Netz... :-O

Letztlich ist diese "Sonderbehandlung" der Xilinx FPGA den umschaltbaren 
Flipflops geschuldet, die entweder snychron oder asynchron arbeiten 
können (Lattice und Altera können da eh' nur den asynchronen Modus). Es 
empfihelt sich also für optimale Performance, die Betrachtungen wie im 
Beitrag "Re: Hardware mit VHDL "richtig" beschreiben." oder im 
Xilixnx WP231 für "seine" Plattform kurz durchzuspielen.

: Bearbeitet durch Moderator
von KaffeKocher (Gast)


Lesenswert?

Holger schrieb:
> KaffeKocher schrieb:
>> Ja hab ich mir schon gedacht, war aber erst mal nur zum Üben. Ich nutze
>> das MachXO2 Pico Board, da hat der FPGA leider keinen Quarz, wobei man
>> höchstwahrscheinlich den Quarz vom FTDI IC auch nutzen kann. War bisher
>> nur zu faul um nachzuschauen :)
> ###################################
> Pico Board habe ich auch, klasse Teil.
> Ja klar geht das, hast du den Stromlaufplan von dem Pico Board.

Stimmt, das geht. Kurze Frage, der Quarz ist ja an so einem "dedicated 
clock pin" angeschlossen. Kann ich nun den Takt einfach direkt von dem 
Pin mithilfe eines Eingangs im Toplevel bekommen, der auf diesen Pin 
konfiguriert ist oder muss ich noch irgendwas instantiieren? So wie es 
für mich aussieht, geht das tatsächlich so einfach.

Holger schrieb:
> Hast du schon mal versucht den Source Code von dem RefDesign des Pico
> Boards zu kompilen. Ich bekomme den für das Pico Board nicht gefittet,
> da der Speicher zu klein ist Typ 1200... . Somit ist das Lattice
> Ref.Design für das PicoBoard eigentlich zum Üben wertlos. So ein Mist
> aber auch.

Nein habe ich noch nicht, aber ich kanns gerne mal ausprobieren, wo 
gibt's denn den Quellcode?

Hast du auch mal auf Größe optimieren lassen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

KaffeKocher schrieb:
> Kann ich nun den Takt einfach direkt von dem Pin mithilfe eines Eingangs
> im Toplevel bekommen
Ja, die Toolchain erkennt den Takt und fügt den nötigen Clockbuffer 
automatisch ein.

von KaffeKocher (Gast)


Lesenswert?

Lothar M. schrieb:
> KaffeKocher schrieb:
>> Kann ich nun den Takt einfach direkt von dem Pin mithilfe eines Eingangs
>> im Toplevel bekommen
> Ja, die Toolchain erkennt den Takt und fügt den nötigen Clockbuffer
> automatisch ein.

Danke, manchmal kann es so einfach sein :)

von Holger (Gast)


Lesenswert?

KaffeKocher schrieb:
> Nein habe ich noch nicht, aber ich kanns gerne mal ausprobieren, wo
> gibt's denn den Quellcode?
>
Allles dabei im RefDesign.. USART SPI_ROM TEMP_SENSOR
Link: Für den Zip.
http://www.latticesemi.com/alpha-mxo2-pico-kit#_C5AFA0531C10491E9706210E995C7F0F

Oben ist so ein Reiter_Menue_BAR .via Mouseklick ..kannst du noch den 
Pdf Doku Stuff da separat Downloaden.

> Hast du auch mal auf Größe optimieren lassen?

War ja ein fertiges Project ... via *.ldf Project File.
Da geht man davon aus das der so eingestellt ist, um das Project zu 
kompilen.

Gruss Holger.

von Holger (Gast)


Angehängte Dateien:

Lesenswert?

Holger schrieb:
> Oben ist so ein Reiter_Menue_BAR .via Mouseklick ..kannst du noch den
> Pdf Doku Stuff da separat Downloaden.

von Holger (Gast)


Lesenswert?

@Kaffekocher hier mein Thread für Lattice PICO Board.
Beitrag "Lattice MachXo2 Bat.Powerd Stand Alone Soc"

Damit kann man prima lernen ... nur halt der Fitter packt das RefDesign 
nicht. Comiler geht.

Viel Erfolg .. Gruss Holger.

von Holger (Gast)


Angehängte Dateien:

Lesenswert?

@Kaffekocher
Hier.. so kannst du mit den ZIP Files lernen.
Gruss Holger.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.