Hallo Leute,
Folgende Eckdaten zu meinem Problem:
FPGA: Lattice iCE40 HX1K
Systemtakt: 100.5 MHz (spuckt der PLL-Generator so "unrund" aus)
Ich möchte ein UART-Modul, dass mit verschiedenen µCs mit verschiedenen
Baudraten kommuniziert, können auch nicht die gängigen sein.
Aus diesem Grund will ich anhand eines Sync-Bytes (0x55 oder 0xAA) vom
µC die Zeit messen, die ein Bit des Inputs anliegt, um bei den
darauffolgenden Datenbits zu wissen, wann der Wert gültig ist. Das Ganze
hab ich mit einer Statemachine umgesetzt.
Kommt eine fallende Flanke am Eingang, starte ich einen Zähler und
stoppe ihn bei einer steigenden Flanke. Das Ganze mach ich 4mal (bzw.
5mal bei 0xAA), dann ist meine UART-Message (8 Datenbits,1 Stopbit) zu
Ende und ich weise den gemessenen Wert einer Variable zu. Das klappt
auch alles wunderbar in der Simulation, nur in der Praxis hauts nicht
ganz hin, hier der relevante Code dazu:
1 | IF rising_edge(clk) THEN
|
2 |
|
3 | rx_detect <= rx_detect(rx_detect'left-1 DOWNTO 0) & uart_rx;
|
4 |
|
5 | CASE uart_rx_mode IS
|
6 |
|
7 | WHEN uart_rx_sync =>
|
8 |
|
9 | CASE uart_sync_state IS
|
10 |
|
11 | WHEN uart_sync_idle =>
|
12 |
|
13 | IF (rx_detect(3 DOWNTO 2) = "10") THEN
|
14 | uart_sync_state <= start_counter;
|
15 | END IF;
|
16 |
|
17 | WHEN start_counter =>
|
18 |
|
19 | IF (rx_detect(3 DOWNTO 2) = "01") THEN
|
20 | uart_sync_state <= stop_counter;
|
21 | END IF;
|
22 |
|
23 | counter_rx <= counter_rx + 1;
|
24 |
|
25 | WHEN stop_counter =>
|
26 |
|
27 | temp <= counter_rx;
|
28 | cnt_value <= cnt_value + counter_rx;
|
29 | cnt_iteration <= cnt_iteration + 1;
|
30 | uart_sync_state <= reset_counter;
|
31 |
|
32 | WHEN reset_counter =>
|
33 |
|
34 | counter_rx <= 0;
|
35 |
|
36 | IF cnt_iteration = 4 THEN
|
37 | uart_sync_state <= sync_values;
|
38 | ELSE
|
39 | uart_sync_state <= uart_sync_idle;
|
40 | END IF;
|
41 |
|
42 | WHEN sync_values =>
|
43 |
|
44 | bit_time <= temp;
|
45 | uart_sync_state <= sync_finished;
|
46 |
|
47 | WHEN sync_finished =>
|
48 |
|
49 | cnt_iteration <= 0;
|
50 | cnt_value <= 0;
|
51 | counter_rx <= 0;
|
52 | temp <= 0;
|
53 | uart_rx_mode <= uart_rx_normal;
|
54 | uart_sync_state <= uart_sync_idle;
|
55 |
|
56 | END CASE;
|
Alle Werte (bit_time,temp,counter_rx,..) sind Signale vom Typ Integer.
Wenn ich die Zuweisung bit_time <= temp; auskommentiere, und bit_time
mit einem festen Wert für eine bestimmte Baudrate initialisiere,
funktioniert alles super, allerdings ist dann eben die Baudrate nicht
variabel...
Auch meine Clock bricht mit dieser Zuweisung ein, mit der Zeile:
(Hier sogar noch über 100MHz, oft aber auch darunter)
Clock Summary
=====================================================================
Number of clocks: 3
Clock: I1.uart_pll_inst/PLLOUTCORE | Frequency: 107.23 MHz | Target:
100.50 MHz
Clock: I1.uart_pll_inst/PLLOUTGLOBAL | Frequency: N/A | Target: 100.50
MHz
Clock: my_clk | Frequency: N/A | Target: 12.00 MHz
Ohne:
Clock Summary
=====================================================================
Number of clocks: 3
Clock: I1.uart_pll_inst/PLLOUTCORE | Frequency: 147.30 MHz | Target:
100.50 MHz
Clock: I1.uart_pll_inst/PLLOUTGLOBAL | Frequency: N/A | Target: 100.50
MHz
Clock: my_clk | Frequency: N/A | Target: 12.00 MHz
Aufgrund der Clock Summarys hab ich nur die Vermutung dass durch die
Zuweisung ein kritischer/zu langer Pfad entsteht, bin mir da aber nicht
sicher (-> noch FPGA-Anfänger)
Seht ihr sonst Fehler, bzw kann man das überhaupt so machen? Gibts
Alternativen?
Leider etwas langer Post geworden, trotzdem danke für jede Hilfe!
MfG
Andreas