Im Praktikum wird mit MAXPlus2 gearbeitet, einige Hinweise zum Setup gab es bereits bei dem PLD Praktikum.
Zum Erstellen von VHDL-Modulen ist die Endung .vhd zu verwenden.
Es sind 2 Aufgaben zu realisieren:
Am Praktikum beteiligt sind:
Termine (Raum 1555):
Thu 09.06.2005 - 15:00h
Thu 02.06.2005 - 15:00h
Aufgabe 1 gelöst
Takt hatte nicht gestimmt (aus der 16 musste ne 32 gemacht werden) - k.A. warum
beim 7 Segment war die 2 falsch
Adresse war verschoben beim MUX (weil Signale erst mit dem nächsten Takt gesetzt werden)
Taster sind low-aktiv
max 1 Takt langer Impuls
Lösung
library IEEE;
use IEEE.std_logic_1164.all;
entity imp_det is
port(
clk, sw_in : in std_logic;
sw_out : out std_logic
);
end imp_det;
architecture A1 of imp_det is
signal d: std_logic;
begin
P1: process (clk)
begin
if (clk'event and clk='1') then
if (d='0' and sw_in='0') then
d<='1';
sw_out<='1';
else
if (sw_in='1') then
d<='0';
end if;
sw_out<='0';
end if;
end if;
end process;
end A1;
Lösung
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity prescal is
port(
gclk: in std_logic;
clk: out std_logic
);
end prescal;
architecture A1 of prescal is
signal tmp_clk: std_logic;
begin
prescaler: process (gclk)
variable prescaler_val: integer range 32 downto 0;
begin
if (gclk'event and gclk = '1') then
prescaler_val:=prescaler_val+1;
if (prescaler_val=32) then
tmp_clk<=not tmp_clk;
clk<=tmp_clk;
prescaler_val:=0;
end if;
end if;
end process;
end A1;
Teilerfaktor (Uhr): 156
Reset und Enable sind high-aktiv
bei Reset, alles auf 0 setzten
bei Enable auf 0 soll das System stehen bleiben
Lösung
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity time_cnt is
port(
clk,cnt_en,reset: in std_logic;
cnt_min,
cnt_sec1,
cnt_sec0,
cnt_mil : out std_logic_vector(3 downto 0)
);
end time_cnt;
architecture A1 of time_cnt is
signal clk_mil,clk_sec: std_logic;
signal tmp_cnt_min,
tmp_cnt_sec1,
tmp_cnt_sec0,
tmp_cnt_mil : integer range 9 downto 0;
begin
prescaler: process (clk)
-- prescaler für die s, es entsteht kein Fehler
-- clk_sec ist der Ausgang
variable prescaler_sec_val: integer range 1024 downto 0;
-- prescaler für die 1/10s, der Fehler beträgt 3.92ms
-- clk_mil ist der Ausgang
variable prescaler_mil_val: integer range 102 downto 0;
begin
if (clk'event and clk='1') then
if (cnt_en='1' and reset='0') then
prescaler_sec_val:=prescaler_sec_val+1;
prescaler_mil_val:=prescaler_mil_val+1;
if (prescaler_sec_val=1024) then
prescaler_sec_val:=0;
clk_sec<='1';
else
clk_sec<='0';
end if;
if (prescaler_mil_val=102) then
prescaler_mil_val:=0;
clk_mil<='1';
else
clk_mil<='0';
end if;
elsif (reset='1') then
prescaler_sec_val:=0;
prescaler_mil_val:=0;
clk_sec<='0';
clk_mil<='0';
end if;
end if;
end process;
-- 1/10s timer
count_mil: process (clk)
variable tmp_cnt_mil : integer range 9 downto 0;
begin
if (clk'event and clk='1') then
if (clk_mil='1' and reset='0' and cnt_en='1') then
if (tmp_cnt_mil=9) then
tmp_cnt_mil:=0;
else
tmp_cnt_mil:=tmp_cnt_mil+1;
end if;
elsif (reset='1') then
tmp_cnt_mil:=0;
end if;
cnt_mil<=conv_std_logic_vector(tmp_cnt_mil,4);
end if;
end process;
-- 1s timer
count_sec: process (clk)
variable tmp_cnt_min,
tmp_cnt_sec1,
tmp_cnt_sec0 : integer range 9 downto 0;
begin
if (clk'event and clk='1') then
if (clk_sec='1' and reset='0' and cnt_en='1') then
if (tmp_cnt_sec0=9) then
tmp_cnt_sec0:=0;
if (tmp_cnt_sec1=5) then
tmp_cnt_sec1:=0;
if (tmp_cnt_min=9) then
tmp_cnt_min:=0;
else
tmp_cnt_min:=tmp_cnt_min+1;
end if;
else
tmp_cnt_sec1:=tmp_cnt_sec1+1;
end if;
else
tmp_cnt_sec0:=tmp_cnt_sec0+1;
end if;
elsif (reset='1') then
tmp_cnt_sec0:=0;
tmp_cnt_sec1:=0;
tmp_cnt_min:=0;
end if;
cnt_sec0<=conv_std_logic_vector(tmp_cnt_sec0,4);
cnt_sec1<=conv_std_logic_vector(tmp_cnt_sec1,4);
cnt_min<=conv_std_logic_vector(tmp_cnt_min,4);
end if;
end process;
end A1;
| Zustand |
| idle | run | inttime | hold |
| z0 | z1 | z2 | z3 |
reset | 1 | 0 | 0 | 0 |
show_int | 0 | 0 | 1 | 0 |
cnt_en | 0 | 1 | 1 | 0 |
Lösung
library IEEE;
use ieee.std_logic_1164.all;
entity main_ctl is
port(
clk,start,stop : in std_logic;
cnt_en,reset,show_int : out std_logic
);
end main_ctl;
architecture A1 of main_ctl is
type state_type is (z0,z1,z2,z3);
signal state: state_type;
begin
prescaler: process (clk)
variable cnt_delay : integer range 8000 downto 0;
begin
if (clk'event and clk='1') then
case state is
--idle
when z0 =>
reset<='0'; show_int<='0'; cnt_en<='0';
if (start='1') then
state<=z1;
end if;
--run
when z1 =>
reset<='0'; show_int<='0'; cnt_en<='1';
if (start='1' and stop='0') then
state<=z2;
elsif (stop='1') then
state<=z3;
end if;
--inttime
when z2 =>
reset<='0'; show_int<='1'; cnt_en<='1';
if (cnt_delay=2048) then
cnt_delay:=0;
state<=z1;
else
cnt_delay:=cnt_delay+1;
end if;
--hold
when z3 =>
reset<='0'; show_int<='0'; cnt_en<='0';
if (start='1' and stop='0') then
state<=z1;
elsif (stop='1') then
reset<='1'; show_int<='0'; cnt_en<='0';
state<=z0;
end if;
end case;
end if;
end process;
end A1;
digit → Auswahl des Anzeigeelementes
segment → low-aktive Signale für 7-Segmentanzeige
bei show_int auf high werden die Eingänge gespeichert und ausgegeben
Lösung
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity bcd7seg is
port(
clk,show_int : in std_logic;
cnt_min,cnt_sec1,
cnt_sec0,cnt_mil : in std_logic_vector(3 downto 0);
segment : out std_logic_vector(6 downto 0);
digit : out std_logic_vector(3 downto 0)
);
end bcd7seg;
architecture A1 of bcd7seg is
signal mux_addr : integer range 3 downto 0;
signal mux_out : integer range 9 downto 0;
begin
latched_mux: process (clk)
variable int_cnt_min,
int_cnt_sec1,int_cnt_sec0,int_cnt_mil : integer range 9 downto 0;
begin
if (clk'event and clk='1') then
if (show_int='0') then
int_cnt_min:=conv_integer(cnt_min);
int_cnt_sec1:=conv_integer(cnt_sec1);
int_cnt_sec0:=conv_integer(cnt_sec0);
int_cnt_mil:=conv_integer(cnt_mil);
end if;
case mux_addr is
when 0 => mux_out<=int_cnt_mil;
when 1 => mux_out<=int_cnt_sec0;
when 2 => mux_out<=int_cnt_sec1;
when 3 => mux_out<=int_cnt_min;
end case;
case mux_out is
when 0 => segment<="1000000";
when 1 => segment<="1111001";
when 2 => segment<="0100100";
when 3 => segment<="0110000";
when 4 => segment<="0011001";
when 5 => segment<="0010010";
when 6 => segment<="0000010";
when 7 => segment<="1111000";
when 8 => segment<="0000000";
when 9 => segment<="0010000";
end case;
end if;
end process;
addr_counter: process (clk)
begin
if (clk'event and clk='1') then
if (mux_addr=3) then
mux_addr<=0;
else
mux_addr<=mux_addr+1;
end if;
case mux_addr is
-- phasenverschiebung oben im mux
when 0 => digit<="1000";
when 1 => digit<="0001";
when 2 => digit<="0010";
when 3 => digit<="0100";
end case;
end if;
end process;
end A1;
Lösung
Zeilen und Spalten codieren
Zeilen
“100” → 0
“010” → 1
“001” → 2
Spalten
“1110” → 1
“1101” → 4
“1011” → 7
“0111” → 10
bestimmen, welche Zeile und Spalte aktiv ist
Spalten werden durchprobiert
bei einem Treffer wird von vorne begonnen
gedrückte Taste wird bestimmt
Taste auswerten
nächste Eingabeadresse auswählen
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity kb_ctrl is
port(
clk : in std_logic;
row : in std_logic_vector (3 downto 0);
digit_0: out std_logic_vector (3 downto 0);
digit_1: out std_logic_vector (3 downto 0);
column : out std_logic_vector (2 downto 0);
freq : out std_logic_vector (5 downto 0)
);
end kb_ctrl;
architecture A1 of kb_ctrl is
signal last_tmp_key : integer range 13 downto 0 := 13;
type dec_digit is array(1 downto 0) of integer range 9 downto 0;
signal digit_val : dec_digit := (0,0);
begin
prescaler: process (clk)
variable tmp_key : integer range 13 downto 0 := 13;
variable tmp_col : integer range 2 downto 0 := 0;
variable tmp_row : integer range 10 downto 0 := 0;
variable tmp_freq : integer range 99 downto 0 := 0;
begin
if (clk'event and clk = '1') then
case row is
when "1110" => tmp_row:=1;
when "1101" => tmp_row:=4;
when "1011" => tmp_row:=7;
when "0111" => tmp_row:=10;
when others => tmp_row:=0;
end case;
if (not (tmp_row=0)) then
-- key detected
tmp_key:=tmp_row+tmp_col;
tmp_col:=2;
if (tmp_key=11) then
tmp_key:=0;
end if;
elsif (tmp_row=0 and tmp_col=2) then
tmp_key:=13;
end if;
-- manage key-changes only
if (not (tmp_key=last_tmp_key)) then
last_tmp_key<=tmp_key;
if (tmp_key=10) then
--* pressed (erase)
digit_val(0)<=0; digit_val(1)<=0;
elsif (tmp_key=12) then
--# pressed (enter)
tmp_freq:=digit_val(0)+digit_val(1)*10;
if (tmp_freq>63) then
tmp_freq:=63; digit_val(1)<=6; digit_val(0)<=3;
--elsif (tmp_freq=0) then
--tmp_freq:=1; digit_val(0)<=1;
end if;
freq<=conv_std_logic_vector(tmp_freq,6);
elsif (not (tmp_key=13)) then
--we got a number
--store it
digit_val(1)<=digit_val(0); digit_val(0)<=tmp_key;
end if;
end if;
-- recalculate our row-adress
if (tmp_col=2) then
tmp_col:=0;
else
tmp_col:=tmp_col+1;
end if;
case tmp_col is
when 0 => column<="100";
when 1 => column<="010";
when 2 => column<="001";
end case;
-- for debugging purpose
digit_0<=conv_std_logic_vector(digit_val(0),4);
digit_1<=conv_std_logic_vector(digit_val(1),4);
end if;
end process;
end A1;
Lösung (von Matthias)
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity KB_CTRL is
port(
clk: in std_logic;
row : in std_logic_vector(3 downto 0);
column : out std_logic_vector(2 downto 0);
frequ : out std_logic_vector(5 downto 0 )
);
end KB_CTRL;
architecture new_architecture of KB_CTRL is
begin
P1: process (clk)
variable key1,key2 : integer range 9 downto 0;
variable result : integer range 11 downto 0;
variable frequ_output : integer range 99 downto 0;
variable input_position,zw_row : integer range 3 downto 0;
variable endinit,var_wait : integer range 1 downto 0;
variable column_output : std_logic_vector(2 downto 0);
begin
if (clk'event and clk='1') then
if ( endinit=1) then -- program code
-- Taste gedrückt
if ( row(0)='0' and var_wait=0) then
var_wait:=1;
zw_row:=0;
elsif ( row(1)='0' and var_wait=0) then
var_wait:=1;
zw_row:=1;
elsif ( row(2)='0' and var_wait=0) then
var_wait:=1;
zw_row:=2;
elsif ( row(3)='0' and var_wait=0) then
var_wait:=1;
zw_row:=3;
elsif ( var_wait=0) then
if ( column_output="100" ) then
column_output:="010";
column<=column_output;
elsif ( column_output="010" ) then
column_output:="001";
column<=column_output;
elsif ( column_output="001" ) then
column_output:="100";
column<=column_output;
end if;
end if;
-- Taste wieder losgelassen
if ( row(0)='1' and var_wait=1 and zw_row=0) then
var_wait:=0;
if ( column_output="100" ) then
result:=1;
elsif ( column_output="010" ) then
result:=2;
elsif ( column_output="001") then
result:=3;
end if;
if ( input_position=1 ) then
key1:=result;
input_position:=2;
elsif ( input_position=2 ) then
key2:=result;
input_position:=3;
elsif ( input_position=3 ) then
-- alles verwerfen, weil nicht # gedrückt wurde -> sprung auf input_position 1
input_position:=1;
end if;
elsif ( row(1)='1' and var_wait=1 and zw_row=1) then
var_wait:=0;
if ( column_output="100" ) then
result:=4;
elsif ( column_output="010" ) then
result:=5;
elsif ( column_output="001") then
result:=6;
end if;
if ( input_position=1 ) then
key1:=result;
input_position:=2;
elsif ( input_position=2 ) then
key2:=result;
input_position:=3;
elsif ( input_position=3 ) then
-- alles verwerfen, weil nicht # gedrückt wurde -> sprung auf input_position 1
input_position:=1;
end if;
elsif ( row(2)='1' and var_wait=1 and zw_row=2) then
var_wait:=0;
if ( column_output="100" ) then
result:=7;
elsif ( column_output="010" ) then
result:=8;
elsif ( column_output="001") then
result:=9;
end if;
if ( input_position=1 ) then
key1:=result;
input_position:=2;
elsif ( input_position=2 ) then
key2:=result;
input_position:=3;
elsif ( input_position=3 ) then
-- alles verwerfen, weil nicht # gedrückt wurde -> sprung auf input_position 1
input_position:=1;
end if;
elsif ( row(3)='1' and var_wait=1 and zw_row=3) then
var_wait:=0;
if ( column_output="100" ) then
result:=10; -- entspricht *
elsif ( column_output="010" ) then
result:=0;
elsif ( column_output="001") then
result:=11; -- entspricht #
end if;
if ( input_position=1 ) then
if ( result=0 ) then
key1:=result;
input_position:=2;
else
-- reset durch input_position auf 1
input_position:=1;
end if;
elsif ( input_position=2 ) then
if ( result=0 ) then
key2:=result;
input_position:=3;
else
-- reset durch input_position auf 1
input_position:=1;
end if;
elsif ( input_position=3 ) then
if ( result=11 ) then
-- checke input auf valid
frequ_output:=key1*10+key2;
if ( frequ_output < 64 ) then
frequ<=conv_std_logic_vector(frequ_output,6);
end if;
else
-- reset durch input_position auf 1
end if;
input_position:=1;
end if;
end if;
elsif ( endinit=0) then
-- init
endinit:=1;
var_wait:=0;
input_position:=1;
column_output:="100";
column<=column_output;
frequ<="000001";
end if;
end if;
end process;
end new_architecture;
Lösung
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ph_acc is
port(
clk : in std_logic;
freq : in std_logic_vector (5 downto 0);
phase: out std_logic_vector (7 downto 0)
);
end ph_acc;
architecture A1 of ph_acc is
begin
counter: process (clk)
variable tmp_phase : integer range 255 downto 0;
variable tmp_freq : integer range 128 downto 0;
begin
if (clk'event and clk = '1') then
tmp_freq:=conv_integer(freq);
tmp_phase:=(tmp_phase+tmp_freq);
if (tmp_freq=0) then tmp_phase:=0; end if;
phase<=conv_std_logic_vector(tmp_phase,8);
end if;
end process;
end A1;
-
ging irgendwie alles nicht, ich habs dann über den MegaWizard Plugin Manager gemacht
und damit gehts auch nicht

es gibt wohl ein Symbol für LPM, das sollte man verwenden
Lösung
library IEEE;
use ieee.std_logic_1164.all;
entity sin_from_table is
port(
clk : in std_logic;
addr : in std_logic_vector (7 downto 0);
sin_amp: out std_logic_vector (7 downto 0)
);
end sin_from_table;
architecture A1 of sin_from_table is
component rom_8x8
-- pragma translate_off
generic (lpm_file : string);
-- pragma translate_on
port (
ADDRESS : in std_logic_vector (7 downto 0);
DATA : out std_logic_vector (7 downto 0)
);
end component;
begin
rom_lookup: process (clk)
begin
--if (clk'event and clk = '1') then
sinrom: rom_8x8
-- pragma translate_off
generic map (lpm_file => "sinrom.mif")
-- pragma translate_on
port map (ADDRESS => addr, DATA => sin_amp);
--end if;
end process;
end A1;