Hallo, besitzt jemand einen Verilog Sample code fuer ein einfaches UART? Wuerde mich mal interessieren wie der aussieht... vlg
Falls Du eine gute Beschreibung in VHDL gefunden hast, dann poste doch bitte mal den Link bzw. Code. Danke, Sebastian
Ich hab die Tage eine kleine UART in VHDL geschrieben...vielleicht nützt es was: Transmitter:
1 | library ieee; |
2 | use ieee.std_logic_1164.all; |
3 | |
4 | entity transmitter is |
5 | port (reset : in std_logic; -- asynch reset |
6 | clk : in std_logic; -- clock 40 MHz |
7 | data : in std_logic_vector(7 downto 0); -- data input |
8 | data_ready : in std_logic; -- control signal |
9 | data ready |
10 | tx_ready : out std_logic; -- transmitter |
11 | ready for new data |
12 | tx : out std_logic); -- transmitter |
13 | output
|
14 | end transmitter; |
15 | |
16 | architecture behavior of transmitter is |
17 | |
18 | -- internal signals |
19 | signal sending : boolean; -- sending mode |
20 | signal sent : boolean; -- sent mode |
21 | signal count_clk : natural range 0 to 4167; -- clock counter |
22 | for clock divider |
23 | signal count_bit : natural range 0 to 10; -- bit counter |
24 | signal enable : std_logic; -- clock enable |
25 | for sending mode |
26 | signal tx_ready_int : std_logic := '1'; -- initalized |
27 | to 1 for tx_ready = 1 on start |
28 | signal data_register : std_logic_vector(7 downto 0); -- for storage of |
29 | data input to send |
30 | |
31 | begin
|
32 | |
33 | |
34 | -------------------------------------
|
35 | -- load tx_ready with rx_ready_int -- |
36 | -------------------------------------
|
37 | tx_ready <= tx_ready_int; |
38 | |
39 | |
40 | --------------------------------------------------
|
41 | -- clock divider for baudrate generation -- |
42 | -- sensitive to clock, asynch reset by received -- |
43 | -- receiving mode: generate clock enable -- |
44 | -- for wished baudrate -- |
45 | --------------------------------------------------
|
46 | clock_divider : process (clk, sent) is |
47 | begin
|
48 | if sent then |
49 | count_clk <= 0; |
50 | elsif clk'event and clk = '1' then |
51 | if sending then |
52 | enable <= '0'; |
53 | if count_clk = 4167 then |
54 | count_clk <= 0; |
55 | elsif count_clk = 0 then |
56 | enable <= '1'; |
57 | count_clk <= count_clk + 1; |
58 | else
|
59 | count_clk <= count_clk + 1; |
60 | end if; |
61 | end if; |
62 | end if; |
63 | end process clock_divider; |
64 | |
65 | |
66 | -----------------------------------------------------------
|
67 | -- data storage of input data -- |
68 | -- sensitive to clock, asynch reset by reset -- |
69 | -- storage data in internal register when data_ready = 1 -- |
70 | -----------------------------------------------------------
|
71 | data_storage : process (clk, reset, sent) is |
72 | begin
|
73 | if reset = '1' or sent then |
74 | data_register <= (others => '0'); |
75 | sending <= false; |
76 | elsif clk'event and clk = '1' then |
77 | if data_ready = '1' then |
78 | if not sending then |
79 | data_register <= data; |
80 | sending <= true; |
81 | end if; |
82 | end if; |
83 | end if; |
84 | end process data_storage; |
85 | |
86 | |
87 | -------------------------------------------------------
|
88 | -- send storaged data -- |
89 | -- sensitive to clock, asynch reset by reset -- |
90 | -- load tx with content of data register from 0 to 9 -- |
91 | -- when sending complete : ready for new data -- |
92 | -------------------------------------------------------
|
93 | data_send : process (clk, reset) is |
94 | begin
|
95 | if reset = '1' then |
96 | tx <= '1'; |
97 | count_bit <= 0; |
98 | elsif clk'event and clk = '1' then |
99 | sent <= false; |
100 | if enable = '1' then |
101 | tx_ready_int <= '0'; |
102 | tx <= '1'; |
103 | case count_bit is |
104 | when 0 => tx <= '0'; |
105 | count_bit <= count_bit + 1; |
106 | when 9 => tx <= '1'; |
107 | count_bit <= count_bit + 1; |
108 | when 10 => tx <= '1'; |
109 | count_bit <= 0; |
110 | sent <= true; |
111 | tx_ready_int <= '1'; |
112 | when others => count_bit <= count_bit + 1; |
113 | tx <= data_register(count_bit - 1); |
114 | end case; |
115 | end if; |
116 | end if; |
117 | end process data_send; |
118 | |
119 | end architecture behavior; |
Receiver:
1 | library ieee; |
2 | use ieee.std_logic_1164.all; |
3 | |
4 | entity receiver is |
5 | port (reset : in std_logic; -- asynch reset |
6 | clk : in std_logic; -- clock 40 MHz |
7 | rx : in std_logic; -- receive |
8 | input
|
9 | data_ready : out std_logic; -- status signal |
10 | data received |
11 | data_error : out std_logic; -- status signal |
12 | receive error |
13 | data_out : out std_logic_vector(7 downto 0)); -- received |
14 | data
|
15 | end receiver; |
16 | |
17 | architecture behaviour of receiver is |
18 | |
19 | signal received : boolean; -- for received |
20 | mode
|
21 | signal receiving : boolean; -- for receive |
22 | mode
|
23 | signal count_start : natural range 0 to 2083; -- start counter |
24 | for detecting middle of startbit |
25 | signal count_clk : natural range 0 to 4167; -- clock counter |
26 | for clock divider |
27 | signal count_bit : natural range 0 to 9; -- bit counter |
28 | for received bits |
29 | signal enable : std_logic; -- clock enable |
30 | for receive mode |
31 | signal data_register : std_logic_vector(7 downto 0); -- data register |
32 | for received bits |
33 | |
34 | |
35 | begin
|
36 | |
37 | |
38 | --------------------------------------------------
|
39 | -- detecting startbit -- |
40 | -- sensitive to clock, asynch reset by received -- |
41 | -- if rx = 0 counts to 2083 to know if there is -- |
42 | -- a startbit -- |
43 | -- when startbit: go in receiving mode -- |
44 | -- when no starbit: count again from 0 to 2083 -- |
45 | --------------------------------------------------
|
46 | sampling : process (clk, received) is |
47 | begin
|
48 | if received then |
49 | receiving <= false; |
50 | count_start <= 0; |
51 | elsif clk'event and clk = '1' then |
52 | if rx = '0' then |
53 | if count_start = 2083 then |
54 | receiving <= true; |
55 | else
|
56 | count_start <= count_start + 1; |
57 | end if; |
58 | end if; |
59 | end if; |
60 | end process sampling; |
61 | |
62 | |
63 | --------------------------------------------------
|
64 | -- clock divider for baudrate generation -- |
65 | -- sensitive to clock, asynch reset by received -- |
66 | -- receiving mode: generate clock enable -- |
67 | -- for wished baudrate -- |
68 | --------------------------------------------------
|
69 | clock_divider: process (clk, received) is |
70 | begin
|
71 | if received then |
72 | count_clk <= 0; |
73 | elsif clk'event and clk = '1' then |
74 | if receiving then |
75 | enable <= '0'; |
76 | if count_clk = 4167 then |
77 | count_clk <= 0; |
78 | elsif count_clk = 0 then |
79 | enable <= '1'; |
80 | count_clk <= count_clk + 1; |
81 | else
|
82 | count_clk <= count_clk + 1; |
83 | end if; |
84 | end if; |
85 | end if; |
86 | end process clock_divider; |
87 | |
88 | |
89 | --------------------------------------------------------
|
90 | -- receive data -- |
91 | -- sensitive to clock. asynch reset by reset -- |
92 | -- clock enable by enable -- |
93 | -- load 9 bit in data register & put data on data out -- |
94 | -- last bit = 1 : valid stopbit => data ready -- |
95 | -- last bit = 0 : invalid stopbit => data error -- |
96 | --------------------------------------------------------
|
97 | data_read: process (clk, reset) is |
98 | begin
|
99 | if reset = '1' then |
100 | data_register <= (others => '0'); |
101 | elsif clk'event and clk = '1' then |
102 | received <= false; |
103 | if enable = '1' then |
104 | data_ready <= '0'; |
105 | data_error <= '0'; |
106 | case count_bit is |
107 | when 0 => count_bit <= count_bit + 1; |
108 | when 9 => count_bit <= 0; |
109 | received <= true; |
110 | data_out <= data_register; |
111 | if rx = '1' then |
112 | data_ready <= '1'; |
113 | else
|
114 | data_error <= '1'; |
115 | end if; |
116 | when others => count_bit <= count_bit + 1; |
117 | data_register(count_bit-1) <= rx; |
118 | end case; |
119 | end if; |
120 | end if; |
121 | end process data_read; |
122 | |
123 | end behaviour; |
Testbench kann ich wenn erwünscht auch liefern...
Hä? Was muss denn seit neusten für VHDL code eingeben? Früher ging mal mal c in eckigen Klammern....
sieht nicht schlecht aus, aber warum nimmst Du für data_register() kein Schieberegister ? Und jeweils oben in TX und RX sollte eine Konstante sein, wo man den Teiler einfach an die Taktfrequenz anpassen kann. Dann wäre es ganz hübsch ... ;-)
@ T.M. gute arbeit. Aber ein c in klammern sagt, das es ein c-Code ist. Mit vhdl am anfang und /VHDL am ende gehts besser :-) Natürlich in eckige klammern.
Ja, ich wollte eh noch generics einführen für die Einstellung der Baudrate... Sowas mach ich immer nachdem ich weiss, dass es prinzipiell funzt ;-) Das mit dem Schieberegister ist natürlich ne Alternative. Muss ich dann mal guggn. Danke :-)
Hy T.M., dein Beitrag ist zwar schon ne Weile her, aber immer noch interessant. Läuft dein UART stabil ? Ich habe bei meinem UART-CORE immer das Problem, das Zeichen beim lesen verschluckt weden ? Hat du vielleicht eine Testbench für deinen UART ? Gruss Ralf Ps.: Ich verwende das Xilinx Spartan3 StarterKitBoard mit dem "PicoBlaze Core von Ken Chapman (Xilinx Ltd) October 2002" und den "UART Transmitter Version 1.00 von Ken Chapman, Xilinx Ltd, Benchmark House".
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.