Forum: FPGA, VHDL & Co. 7-Seg Pins ansteuern


von Max K. (mku)


Angehängte Dateien:

Lesenswert?

hi

ich habe mir ein devlopmentboard zugelegt und zwar das: A-C8V4 von 
21EDA. (also schön chinesisch)
http://www.ebay.de/itm/281285779925?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649

An sich schon mal ein schönes board.

Ich bin auch gerade am durchtesten der beigelegten Software. 
Bedauerlicherweise ist alles in Verilog geschrieben. Ich selber habe nur 
VHDL in der Uni gelernt.

Ich habe jetzt z.B. dieses Programm:
1
//ÉîÛÚÊÐ21EDAµç×Ó.
2
//¿ª·¢°åÐͺÅ:A-C8V4
3
//www.21eda.com
4
//£·¶ÎÊýÂë¹Ü²âÊÔʵÑ飺ÒÔ¶¯Ì¬É¨Ã跽ʽÔÚ£¸Î»ÊýÂë¹Ü
5
//¡°Í¬Ê±¡±ÏÔʾ£°--7
6
//ʵÑéµÄÄ¿µÄÊÇÏòÓû§½éÉܶà¸öÊýÂë¹Ü¶¯Ì¬ÏÔʾµÄ·½·¨¡£
7
//¶¯Ì¬ÏÔʾµÄ·½·¨ÊÇ£¬°´Ò»¶¨µÄƵÂÊÂÖÁ÷Ïò¸÷¸öÊýÂë¹ÜµÄCOM¶ËËͳöµÍµçƽ
8
//ͬʱËͳö¶ÔÓ¦µÄÊý¾Ý¸ø¸÷¶Î
9
10
11
module led_0_7 (clk,rst,dataout,en);
12
13
input clk,rst;         //ϵͳʱÖÓ50MÊäÈë ´Ó12½ÅÊäÈë¡£
14
output[7:0] dataout;   //ÊýÂë¹ÜµÄ¶ÎÂëÊä³ö
15
output[7:0] en;        //ÊýÂë¹ÜµÄλѡʹÄÜÊä³ö
16
17
reg[7:0] dataout;     
18
reg[7:0] en;
19
20
reg[15:0] cnt_scan;   //ÊýÂë¹ÜµÄɨÃèÏÔʾ¼ÆÊýÆ÷
21
reg[4:0] dataout_buf;
22
23
always@(posedge clk or negedge  rst)
24
begin
25
  if(!rst) begin
26
    cnt_scan<=0;
27
    
28
   end
29
  else begin
30
    cnt_scan<=cnt_scan+1;
31
                  //ÊýÂë¹ÜµÄɨÃèÏÔʾ¼ÆÊýÆ÷×Ô¼Ó
32
    end
33
end
34
35
always @(cnt_scan)
36
begin
37
   case(cnt_scan[15:13])
38
                //caseÓï¾äµÄ¹¦ÄÜÊÇ°Ñÿһ¸öÊýÂë¹ÜÂÖÁ÷µãÁÁ¡£
39
                //ÐÞ¸Äcnt_scan[15:13]£¬¿ÉÒÔÐÞ¸ÄÊýÂë¹ÜµÄÏÔʾƵÂÊ¡£
40
       3'b000 :
41
          en = 8'b1111_1110;  //µãÁÁµÚһλÊýÂë¹Ü
42
43
       3'b001 :
44
          en = 8'b1111_1101;
45
46
       3'b010 :
47
          en = 8'b1111_1011;
48
49
       3'b011 :
50
          en = 8'b1111_0111;
51
52
       3'b100 :
53
          en = 8'b1110_1111;
54
55
       3'b101 :
56
          en = 8'b1101_1111;
57
58
       3'b110 :
59
          en = 8'b1011_1111;
60
61
       3'b111 :
62
          en = 8'b0111_1111;
63
64
       default :
65
          en = 8'b1111_1110;  //µãÁÁµÚ°ËλÊýÂë¹Ü
66
    endcase
67
end
68
always@(en) //¶ÔÓ¦COMÐźŸø³ö¸÷¶ÎÊý¾Ý
69
begin
70
  case(en)
71
    8'b1111_1110:          //¸ù¾Ý²»Í¬µÄʹÄÜÐźš£
72
      dataout_buf=0; //ÊýÂë¹ÜÏÔʾ²»Í¬µÄÊý×Ö
73
    8'b1111_1101:
74
      dataout_buf=1;
75
    8'b1111_1011:
76
      dataout_buf=2;
77
    8'b1111_0111:
78
      dataout_buf=3;  
79
    8'b1110_1111:
80
      dataout_buf=4;
81
    8'b1101_1111:
82
      dataout_buf=5;
83
    8'b1011_1111:
84
      dataout_buf=6;
85
    8'b0111_1111:
86
      dataout_buf=7;
87
    default: 
88
      dataout_buf=8;
89
   endcase
90
end
91
92
always@(dataout_buf)
93
begin
94
95
  case(dataout_buf)
96
    4'b0000:
97
      dataout=8'b1100_0000; //¹²ÑôÊýÂë¹ÜÏÔʾ0µÄ¶ÎÂë
98
    4'b0001:
99
      dataout=8'b1111_1001;
100
    4'b0010:
101
      dataout=8'b1010_0100;
102
    4'b0011:
103
      dataout=8'b1011_0000;
104
    4'b0100:
105
      dataout=8'b1001_1001;
106
    4'b0101:
107
      dataout=8'b1001_0010;
108
    4'b0110:
109
      dataout=8'b1000_0010;
110
    4'b0111:
111
      dataout=8'b1111_1000; //¹²ÑôÊýÂë¹ÜÏÔʾ7µÄ¶ÎÂë
112
    default: 
113
      dataout=8'b1000_0000;
114
   endcase
115
end
116
117
endmodule

Dieser Code zeigt auf den 8 7-Segmentanzeigen die Zahlen 7 6 5 4 3 2 1 0 
an.

Als Pinzuweisung wurde wie im Bild programmiert.
Wie kann ich jetzt jeden "Strich" einzeln ansprechen?
Beim DE2-70 Board, welches wir in der Uni haben, kann man jeden "Strich" 
einzeln ansprechen.
Heißt das, dass ich einen Multiplexer zur ansteuerung benötige, wo dann 
mit hoher frequenz jede Zahl einzeln geschrieben wird? (vielleicht in 
dem Beispielprogramm "cnt_scan"

Danke :)

von Thomas T. (knibbel)


Lesenswert?

Hallo,

ja, dass wird zwangsläufig auf einen Multiplexer hinauslaufen.

In der Beispiel-BESCHREIBUNG(!) (ich sehe hier keine Programme...) ist 
cnt_scan ein 16 Bit-Zähler, welcher bei jedem Eingangstakt inkrementiert 
(siehe ersten always-Block).

Für den Multiplexer werden aber nur die höchsten 3 Bits verwendet und 
daraus das jeweilige Display enabled (durch setzen des Ausgangs auf 0) 
(siehe zweiten always-Block).

Der dritte always-Block nimmt sich das Enable-Wort (welches eigentlich 
die Ausgänge setzt) und besetzt entsprechend dataout_buf mit einem Wert 
von 0 bis 7 (die 8 bei default dürfte nicht auftreten...)

Der vierte always-Block setzt nun die Datenausgänge in Abhängigkeit des 
"dataout_buf"-Wertes. Hier könntes Du theoretisch die "leuchtenden 
Striche" ändern.

Hoffe, das hilft Dir etwas weiter. LED-Multiplexer in VHDL finden sich 
aber im Netz, da diese Verdrahtung auch z.B. bei einem Spartan3-Board 
von Digilent gegeben ist.

Gruß und viel Erfolg,
Thomas

: Bearbeitet durch User
von Max K. (mku)


Lesenswert?

habe es nun gestern hin bekommen.

Das schlimmste war im grunde der Takt, da ich bei der PLL nie unter 10 
MHz einstellen konnte, warscheinlich wegen dem Cyclon II EP2C8Q208C8N.
Ansonsten wäre es zu schnell gewesen und man konnte nichts erkennen.

musste also dazu einen Taktteiler nehmen, den ich damals aus der Uni 
hatte, welcher letzendlich nur aus einem Zähler besteht. Aber dazu muss 
man erstmal durchblicken.

hoffe es sind 2kHz (FPGA_freq hat einen integer wert von 50000000) und 
wird mit 50MHz betrieben:
1
if (count6 < FPGA_freq/50000) then
2
          clk2khz <= '0';
3
          count6 <= count6 + 1;
4
        elsif (count6 < (FPGA_freq/25000)-1) then 
5
          clk2khz <= '1';
6
          count6 <= count6 + 1;
7
        else
8
          count6 <= 0;
9
        end if;


dazu habe ich dann mit diesem kleinen Code das Wort HALLO und einen 
strich der pro sekunde blinkt:
um die schatten zu reduzieren, habe ich immer zwischen den schritten 
alle ausgeschaltet. Durch die 2khz trotzdem nicht erkennbar.
1
-- 7-Seg ansteuern
2
3
library ieee;
4
use ieee.std_logic_1164.all;
5
use ieee.numeric_std.all;
6
use ieee.std_logic_arith.all;
7
8
entity seg is
9
10
  port
11
  (
12
    clk50          : in std_logic;
13
    reset          : in std_logic;
14
    s_takt        : in std_logic;
15
    
16
    segment        : out std_logic_vector(7 downto 0); -- welcher strich angesprochen wird    
17
    bereich        : out std_logic_vector(7 downto 0) -- welche 7-Seg angesprochen werden soll
18
19
    
20
  );
21
22
end entity;
23
24
architecture rtl of seg is
25
26
begin
27
28
  process (clk50, reset)
29
30
  variable     cnt : integer range 0 to 15;
31
  
32
  begin
33
---------------------------------------------------------------  
34
                        -- reset
35
    if reset = '0' then
36
      cnt   := 0;
37
      segment <= "00000000";      
38
      bereich <= "00000000";
39
      
40
---------------------------------------------------------------          
41
    elsif (falling_edge(clk50)) then
42
          
43
      if cnt < 15 then
44
        cnt := cnt +1;
45
      else
46
        cnt := 0;
47
      end if;
48
      
49
      
50
      case cnt is  
51
          when 0 =>   bereich <= "01111111";
52
                  segment <= "00000010";
53
          when 1 =>   bereich <= "11111111";      -- loeschen der segmente, da sonst schattenbildung
54
          when 2 =>   bereich <= "10111111";
55
                  segment <= "11100011";
56
          when 3 =>   bereich <= "11111111";
57
          when 4 =>   bereich <= "11011111";
58
                  segment <= "11100011";
59
          when 5 =>   bereich <= "11111111";
60
          when 6 =>   bereich <= "11101111";
61
                  segment <= "00010001";
62
          when 7 =>   bereich <= "11111111";
63
          when 8 =>   bereich <= "11110111";
64
                  segment <= "10010001";  
65
          when 9 =>   bereich <= "11111111";
66
          when 10 =>   bereich <= "11111011";
67
                  segment <= "11111111";
68
          when 11 =>   bereich <= "11111111";
69
          when 12 =>   bereich <= "11111101";
70
                  segment <= "11111111";
71
          when 13 =>   bereich <= "11111111"; -- loeschen
72
          when 14 =>
73
            if s_takt = '1' then
74
              bereich <= "11111110";
75
              segment <= "11111101";
76
            else
77
              bereich <= "11111111";
78
              segment <= "11111101";
79
            end if;
80
          when 15 => bereich <= "11111111";
81
82
      end case;
83
        
84
    end if; -- elsif
85
          
86
  end process;
87
88
end rtl;

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


Lesenswert?

1
        if (count6 < FPGA_freq/50000) then
2
          clk2khz <= '0';
3
          count6 <= count6 + 1;
4
        elsif (count6 < (FPGA_freq/25000)-1) then 
5
          clk2khz <= '1';
6
          count6 <= count6 + 1;
7
        else
8
          count6 <= 0;
9
        end if;
So macht man keine Takte!
Sondern bestenfalls Clock-Enables:
1
        clk2khz <= '0';
2
        if (count6 < FPGA_freq/50000-1) then  -- MINUS 1 NICHT VERGESSEN!!!
3
          count6 <= count6 + 1;
4
        else
5
          clk2khz <= '1';
6
          count6  <= 0;
7
        end if;
Das "minus 1" nicht vergessen! Sonst zählst du einen Takt zu viel. Denn 
z.B. sind es von 0...5 schon 6 Takte: 0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3...

Max K. schrieb:
> Ansonsten wäre es zu schnell gewesen und man konnte nichts erkennen.
Jetzt wird das Problem langsam klarer.

> musste also dazu einen Taktteiler nehmen, den ich damals aus der Uni
> hatte, welcher letzendlich nur aus einem Zähler besteht.
So wird kein Takt erzeugt!

> Aber dazu muss man erstmal durchblicken.
Achtung: du bist noch auf dem falschen Weg!

> hoffe es sind 2kHz (FPGA_freq hat einen integer wert von 50000000)
Dann mach es wie ich hier beim Lauflicht:
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html
Das ganze Design läuft mit 10MHz und deas Lauflicht taktet trotzden nur 
dreimal pro Sekunde.
Oder wie hier bei der Baudratenerzeugung:
http://www.lothar-miller.de/s9y/archives/48-RS232.html
Oder beim DCF77-Decoder:
http://www.lothar-miller.de/s9y/archives/77-DCF77-Decoder.html
Oder:
http://www.lothar-miller.de/s9y/categories/47-PWM
Oder:
http://www.lothar-miller.de/s9y/archives/63-RC-5-Empfaenger.html
Immer das selbe: das gesamte Design läuft mit ein und demselben Takt. 
Nur werden über Vorteiler irgendwelche Komponenten erst nach Ablauf 
einiger Takte aktiv.

von Thomas T. (knibbel)


Lesenswert?

Hallo,

mir fielen noch ein paar Details auf:

A) Dein Design arbeitet mit einem negativen Takt. Kann man machen, 
muss man hier aber nicht. Vielleicht ist das auch nur meine Angewohnheit 
immer auf eine positve Taktflanke zu triggern...

B) Du hast einen asynchronen Reset drin. Lege den Resetteil mit ein den 
synchronen Teil. (Wenn Du schon auf Lothars Seiten bist, dann schau Dir 
auch gleich seine Ausführungen zu asynchronen Resets an...)

C) Im Resetteil schaltest Du alle Displays an (bereich <= "00000000"), 
eher solltest Du alle Displays ausschalten (bereich <= "11111111").

D) Du musst hier nicht mit PLLs oder Ähnlichen Sachen arbeiten. Das geht 
viel einfacher, wenn Du Dir das chinesische Verilog-Beispiel genau 
anschaust:

Hier wird ein 16 Bit-Zähler benutzt, von denen Bit 15, 14 und Bit 13 für 
deine CASE-Abfrage verwendet werden können. Du lässt diesen 16 
Bit-Zähler einfach mit dem 50MHz-Takt hochzählen. Die unteren 13 Bit vom 
Zähler "takten" dann bei jedem Überlauf dieses 13 Bit-Zählers (Bit 12 
bis Bit 0) den 3 Bit-Zähler (Bit 15 bis Bit 13). Das heisst, Du hast 
automatisch einen Vorteiler von 2 hoch 13, also von 8192. Dadurch zählt 
dann dein Zähler für die CASE-Abfrage mit einer Frequenz von etwas über 
6kHz. Das ist gar nicht mehr so schnell. Damit kannst Du Dir dann auch 
die Zwischenstufen für das Übersprechen der Segmente sparen...

Gruß,
Thomas

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.