diff --git a/cores/curso/ch04/fifo_test.prj b/cores/curso/ch04/fifo_test.prj index 4255fac..a49c2a5 100644 --- a/cores/curso/ch04/fifo_test.prj +++ b/cores/curso/ch04/fifo_test.prj @@ -1,2 +1,3 @@ vhdl work "list_ch04_21_fifo_test.vhd" vhdl work "list_ch04_20_fifo.vhd" +vhdl work "debounce.vhd" diff --git a/cores/curso/ch04/list_ch04_19_watch_test.vhd b/cores/curso/ch04/list_ch04_19_watch_test.vhd index 6d93c7e..9669ec3 100644 --- a/cores/curso/ch04/list_ch04_19_watch_test.vhd +++ b/cores/curso/ch04/list_ch04_19_watch_test.vhd @@ -5,7 +5,6 @@ entity stop_watch_test is port( clk: in std_logic; bot: in std_logic_vector(4 downto 0); - sw: in std_logic_vector(7 downto 0); led: out std_logic_vector(4 downto 0); an: out std_logic_vector(3 downto 0); sseg: out std_logic_vector(7 downto 0) diff --git a/cores/curso/ch04/stop_watch_test.prj b/cores/curso/ch04/stop_watch_test.prj index dd31860..1988509 100644 --- a/cores/curso/ch04/stop_watch_test.prj +++ b/cores/curso/ch04/stop_watch_test.prj @@ -1,2 +1,3 @@ vhdl work "list_ch04_19_watch_test.vhd" vhdl work "list_ch04_17_18_watch.vhd" +vhdl work "list_ch04_15_disp_hex.vhd" diff --git a/cores/curso/ch05/ch05_zxuno_v4.ucf b/cores/curso/ch05/ch05_zxuno_v4.ucf new file mode 100644 index 0000000..617c55b --- /dev/null +++ b/cores/curso/ch05/ch05_zxuno_v4.ucf @@ -0,0 +1,52 @@ +#======================================================== +# clock +#======================================================== +NET "clk" LOC="P55" | IOSTANDARD=LVCMOS33; + +#======================================================== +# buttons & switches +#======================================================== +# 5 push buttons +NET "bot<0>" LOC="P6" | IOSTANDARD=LVCMOS33 | PULLUP; #left +NET "bot<1>" LOC="P7" | IOSTANDARD=LVCMOS33 | PULLUP; #right +NET "bot<2>" LOC="P1" | IOSTANDARD=LVCMOS33 | PULLUP; #up +NET "bot<3>" LOC="P5" | IOSTANDARD=LVCMOS33 | PULLUP; #down +NET "bot<4>" LOC="P2" | IOSTANDARD=LVCMOS33 | PULLUP; #fire + +# 8 slide switches +NET "sw<0>" LOC="P51" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<1>" LOC="P46" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<2>" LOC="P45" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<3>" LOC="P50" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<4>" LOC="P48" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<5>" LOC="P57" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<6>" LOC="P56" | IOSTANDARD=LVCMOS33 | PULLUP; +NET "sw<7>" LOC="P58" | IOSTANDARD=LVCMOS33 | PULLUP; + +#======================================================== +# 4-digit time-multiplexed 7-segment LED display +#======================================================== +# digit enable +NET "an<0>" LOC="P30" | IOSTANDARD=LVCMOS33; +NET "an<1>" LOC="P29" | IOSTANDARD=LVCMOS33; +NET "an<2>" LOC="P15" | IOSTANDARD=LVCMOS33; +NET "an<3>" LOC="P32" | IOSTANDARD=LVCMOS33; + +# 7-segment led segments +NET "sseg<7>" LOC="P23" | IOSTANDARD=LVCMOS33; # decimal point +NET "sseg<6>" LOC="P16" | IOSTANDARD=LVCMOS33; # segment a +NET "sseg<5>" LOC="P22" | IOSTANDARD=LVCMOS33; # segment b +NET "sseg<4>" LOC="P24" | IOSTANDARD=LVCMOS33; # segment c +NET "sseg<3>" LOC="P12" | IOSTANDARD=LVCMOS33; # segment d +NET "sseg<2>" LOC="P21" | IOSTANDARD=LVCMOS33; # segment e +NET "sseg<1>" LOC="P26" | IOSTANDARD=LVCMOS33; # segment f +NET "sseg<0>" LOC="P27" | IOSTANDARD=LVCMOS33; # segment g + +#======================================================== +# 5 discrete led +#======================================================== +NET "led<0>" LOC="P34" | IOSTANDARD=LVCMOS33; +NET "led<1>" LOC="P35" | IOSTANDARD=LVCMOS33; +NET "led<2>" LOC="P41" | IOSTANDARD=LVCMOS33; +NET "led<3>" LOC="P43" | IOSTANDARD=LVCMOS33; +NET "led<4>" LOC="P47" | IOSTANDARD=LVCMOS33; diff --git a/cores/curso/ch05/debounce_test.prj b/cores/curso/ch05/debounce_test.prj new file mode 100644 index 0000000..5b120a4 --- /dev/null +++ b/cores/curso/ch05/debounce_test.prj @@ -0,0 +1,2 @@ +vhdl work "list_ch05_07_db_test.vhd" +vhdl work "list_ch05_06_debounce.vhd" diff --git a/cores/curso/ch05/debounce_test.ut b/cores/curso/ch05/debounce_test.ut new file mode 100644 index 0000000..a9facca --- /dev/null +++ b/cores/curso/ch05/debounce_test.ut @@ -0,0 +1,30 @@ +-w +-g Binary:no +-g Compress +-g CRC:Enable +-g Reset_on_err:No +-g ConfigRate:2 +-g ProgPin:PullUp +-g TckPin:PullUp +-g TdiPin:PullUp +-g TdoPin:PullUp +-g TmsPin:PullUp +-g UnusedPin:PullDown +-g UserID:0xFFFFFFFF +-g ExtMasterCclk_en:No +-g SPI_buswidth:1 +-g TIMER_CFG:0xFFFF +-g multipin_wakeup:No +-g StartUpClk:CClk +-g DONE_cycle:4 +-g GTS_cycle:5 +-g GWE_cycle:6 +-g LCK_cycle:NoWait +-g Security:None +-g DonePipe:No +-g DriveDone:No +-g en_sw_gsr:No +-g drive_awake:No +-g sw_clk:Startupclk +-g sw_gwe_cycle:5 +-g sw_gts_cycle:4 diff --git a/cores/curso/ch05/debounce_test.xst b/cores/curso/ch05/debounce_test.xst new file mode 100644 index 0000000..38bd824 --- /dev/null +++ b/cores/curso/ch05/debounce_test.xst @@ -0,0 +1,53 @@ +set -tmpdir "projnav.tmp" +set -xsthdpdir "xst" +run +-ifn debounce_test.prj +-infer_ramb8 No -loop_iteration_limit 32768 +-ofn debounce_test +-ofmt NGC +-p xc6slx9-2-tqg144 +-top debounce_test +-opt_mode Speed +-opt_level 2 +-power NO +-uc "timings.xcf" +-iuc NO +-keep_hierarchy No +-netlist_hierarchy As_Optimized +-rtlview Yes +-glob_opt AllClockNets +-read_cores YES +-write_timing_constraints YES +-cross_clock_analysis NO +-hierarchy_separator / +-bus_delimiter <> +-case Maintain +-slice_utilization_ratio 100 +-bram_utilization_ratio 100 +-dsp_utilization_ratio 100 +-lc Auto +-reduce_control_sets Auto +-fsm_extract NO +-fsm_style LUT +-ram_extract Yes +-ram_style Auto +-rom_extract Yes +-shreg_extract YES +-rom_style Auto +-auto_bram_packing NO +-resource_sharing YES +-async_to_sync YES +-shreg_min_size 2 +-use_dsp48 Auto +-iobuf YES +-max_fanout 100000 +-bufg 16 +-register_duplication YES +-register_balancing No +-optimize_primitives NO +-use_clock_enable Auto +-use_sync_set Auto +-use_sync_reset Auto +-iob Auto +-equivalent_register_removal YES +-slice_utilization_ratio_maxmargin 5 diff --git a/cores/curso/ch05/list_ch05_01_02_fsm_eg.vhd b/cores/curso/ch05/list_ch05_01_02_fsm_eg.vhd new file mode 100644 index 0000000..45e8090 --- /dev/null +++ b/cores/curso/ch05/list_ch05_01_02_fsm_eg.vhd @@ -0,0 +1,118 @@ +-- Listing 5.1 +library ieee; +use ieee.std_logic_1164.all; +entity fsm_eg is + port( + clk, reset: in std_logic; + a, b: in std_logic; + y0, y1: out std_logic + ); +end fsm_eg; + +architecture mult_seg_arch of fsm_eg is + type eg_state_type is (s0, s1, s2); + signal state_reg, state_next: eg_state_type; +begin + -- state register + process(clk,reset) + begin + if (reset='1') then + state_reg <= s0; + elsif (clk'event and clk='1') then + state_reg <= state_next; + end if; + end process; + -- next-state logic + process(state_reg,a,b) + begin + case state_reg is + when s0 => + if a='1' then + if b='1' then + state_next <= s2; + else + state_next <= s1; + end if; + else + state_next <= s0; + end if; + when s1 => + if (a='1') then + state_next <= s0; + else + state_next <= s1; + end if; + when s2 => + state_next <= s0; + end case; + end process; + -- Moore output logic + process(state_reg) + begin + case state_reg is + when s0|s1 => + y1 <= '0'; + when s2 => + y1 <= '1'; + end case; + end process; + -- Mealy output logic + process(state_reg,a,b) + begin + case state_reg is + when s0 => + if (a='1') and (b='1') then + y0 <= '1'; + else + y0 <= '0'; + end if; + when s1 | s2 => + y0 <= '0'; + end case; + end process; +end mult_seg_arch; + + +-- Listing 5.2 +architecture two_seg_arch of fsm_eg is + type eg_state_type is (s0, s1, s2); + signal state_reg, state_next: eg_state_type; +begin + -- state register + process(clk,reset) + begin + if (reset='1') then + state_reg <= s0; + elsif (clk'event and clk='1') then + state_reg <= state_next; + end if; + end process; + -- next-state/output logic + process(state_reg,a,b) + begin + state_next <= state_reg; -- default back to same state + y0 <= '0'; -- default 0 + y1 <= '0'; -- default 0 + case state_reg is + when s0 => + y1 <= '1'; + if a='1' then + if b='1' then + state_next <= s2; + y0 <= '1'; + else + state_next <= s1; + end if; + -- no else branch + end if; + when s1 => + y1 <= '1'; + if (a='1') then + state_next <= s0; + -- no else branch + end if; + when s2 => + state_next <= s0; + end case; + end process; +end two_seg_arch; \ No newline at end of file diff --git a/cores/curso/ch05/list_ch05_03_04_05_edge.vhd b/cores/curso/ch05/list_ch05_03_04_05_edge.vhd new file mode 100644 index 0000000..07b7a98 --- /dev/null +++ b/cores/curso/ch05/list_ch05_03_04_05_edge.vhd @@ -0,0 +1,98 @@ +-- Listing 5.3 +library ieee; +use ieee.std_logic_1164.all; +entity edge_detect is + port( + clk, reset: in std_logic; + level: in std_logic; + tick: out std_logic + ); +end edge_detect; + +architecture moore_arch of edge_detect is + type state_type is (zero, edge, one); + signal state_reg, state_next: state_type; +begin + -- state register + process(clk,reset) + begin + if (reset='1') then + state_reg <= zero; + elsif (clk'event and clk='1') then + state_reg <= state_next; + end if; + end process; + -- next-state/output logic + process(state_reg,level) + begin + state_next <= state_reg; + tick <= '0'; + case state_reg is + when zero=> + if level= '1' then + state_next <= edge; + end if; + when edge => + tick <= '1'; + if level= '1' then + state_next <= one; + else + state_next <= zero; + end if; + when one => + if level= '0' then + state_next <= zero; + end if; + end case; + end process; +end moore_arch; + +-- Listing 5.4 +architecture mealy_arch of edge_detect is + type state_type is (zero, one); + signal state_reg, state_next: state_type; +begin + -- state register + process(clk,reset) + begin + if (reset='1') then + state_reg <= zero; + elsif (clk'event and clk='1') then + state_reg <= state_next; + end if; + end process; + -- next-state/output logic + process(state_reg,level) + begin + state_next <= state_reg; + tick <= '0'; + case state_reg is + when zero=> + if level= '1' then + state_next <= one; + tick <= '1'; + end if; + when one => + if level= '0' then + state_next <= zero; + end if; + end case; + end process; +end mealy_arch; + +-- Listing 5.5 +architecture gate_level_arch of edge_detect is + signal delay_reg: std_logic; +begin + -- delay register + process(clk,reset) + begin + if (reset='1') then + delay_reg <= '0'; + elsif (clk'event and clk='1') then + delay_reg <= level; + end if; + end process; + -- decoding logic + tick <= (not delay_reg) and level; +end gate_level_arch; \ No newline at end of file diff --git a/cores/curso/ch05/list_ch05_06_debounce.vhd b/cores/curso/ch05/list_ch05_06_debounce.vhd new file mode 100644 index 0000000..fcffa81 --- /dev/null +++ b/cores/curso/ch05/list_ch05_06_debounce.vhd @@ -0,0 +1,116 @@ +-- Listing 5.6 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity db_fsm is + port( + clk, reset: in std_logic; + sw: in std_logic; + db: out std_logic + ); +end db_fsm; + +architecture arch of db_fsm is + constant N: integer:=19; -- 2^N * 20ns = 10ms tick + signal q_reg, q_next: unsigned(N-1 downto 0); + signal m_tick: std_logic; + type eg_state_type is (zero,wait1_1,wait1_2,wait1_3, + one,wait0_1,wait0_2,wait0_3); + signal state_reg, state_next: eg_state_type; +begin + --=================================== + -- counter to generate 10 ms tick + -- (2^19 * 20ns) + --=================================== + process(clk,reset) + begin + if (clk'event and clk='1') then + q_reg <= q_next; + end if; + end process; + -- next-state logic + q_next <= q_reg + 1; + --output tick + m_tick <= '1' when q_reg=0 else + '0'; + --=================================== + -- debouncing FSM + --=================================== + -- state register + process(clk,reset) + begin + if (reset='1') then + state_reg <= zero; + elsif (clk'event and clk='1') then + state_reg <= state_next; + end if; + end process; + -- next-state/output logic + process(state_reg,sw,m_tick) + begin + state_next <= state_reg; --default: back to same state + db <= '0'; -- default 0 + case state_reg is + when zero => + if sw='1' then + state_next <= wait1_1; + end if; + when wait1_1 => + if sw='0' then + state_next <= zero; + else + if m_tick='1' then + state_next <= wait1_2; + end if; + end if; + when wait1_2 => + if sw='0' then + state_next <= zero; + else + if m_tick='1' then + state_next <= wait1_3; + end if; + end if; + when wait1_3 => + if sw='0' then + state_next <= zero; + else + if m_tick='1' then + state_next <= one; + end if; + end if; + when one => + db <='1'; + if sw='0' then + state_next <= wait0_1; + end if; + when wait0_1 => + db <='1'; + if sw='1' then + state_next <= one; + else + if m_tick='1' then + state_next <= wait0_2; + end if; + end if; + when wait0_2 => + db <='1'; + if sw='1' then + state_next <= one; + else + if m_tick='1' then + state_next <= wait0_3; + end if; + end if; + when wait0_3 => + db <='1'; + if sw='1' then + state_next <= one; + else + if m_tick='1' then + state_next <= zero; + end if; + end if; + end case; + end process; +end arch; \ No newline at end of file diff --git a/cores/curso/ch05/list_ch05_07_db_test.vhd b/cores/curso/ch05/list_ch05_07_db_test.vhd new file mode 100644 index 0000000..7749359 --- /dev/null +++ b/cores/curso/ch05/list_ch05_07_db_test.vhd @@ -0,0 +1,77 @@ +-- Listing 5.7 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity debounce_test is + port( + clk: in std_logic; + bot: in std_logic_vector(4 downto 0); + led: out std_logic_vector(4 downto 0); + an: out std_logic_vector(3 downto 0); + sseg: out std_logic_vector(7 downto 0) + ); +end debounce_test; + +architecture arch of debounce_test is + signal btn: std_logic_vector(3 downto 0); + signal q1_reg, q1_next: unsigned(7 downto 0); + signal q0_reg, q0_next: unsigned(7 downto 0); + signal b_count, d_count: std_logic_vector(7 downto 0); + signal btn_reg, db_reg: std_logic; + signal db_level, db_tick, btn_tick, clr: std_logic; +begin + + btn <= not bot(3 downto 0); + led <= not bot; + + --================================================= + -- component instantiation + --================================================= + -- instantiate hex display time-multiplexing circuit + disp_unit: entity work.disp_hex_mux + port map( + clk=>clk, reset=>'0', + hex3=>b_count(7 downto 4), hex2=>b_count(3 downto 0), + hex1=>d_count(7 downto 4), hex0=>d_count(3 downto 0), + dp_in=>"1011", an=>an, sseg=>sseg); + -- instantiate debouncing circuit + db_unit: entity work.db_fsm(arch) + port map( + clk=>clk, reset=>'0', + sw=>btn(1), db=>db_level); + + --================================================= + -- edge detection circuits + --================================================= + process(clk) + begin + if (clk'event and clk='1') then + btn_reg <= btn(1); + db_reg <= db_level; + end if; + end process; + btn_tick <= (not btn_reg) and btn(1); + db_tick <= (not db_reg) and db_level; + + --================================================= + -- two counters + --================================================= + clr <= btn(0); + process(clk) + begin + if (clk'event and clk='1') then + q1_reg <= q1_next; + q0_reg <= q0_next; + end if; + end process; + -- next-state logic for the counter + q1_next <= (others=>'0') when clr='1' else + q1_reg + 1 when btn_tick='1' else + q1_reg; + q0_next <= (others=>'0') when clr='1' else + q0_reg + 1 when db_tick='1' else + q0_reg; + --output + b_count <= std_logic_vector(q1_reg); + d_count <= std_logic_vector(q0_reg); +end arch; diff --git a/cores/curso/ch05/make.bat b/cores/curso/ch05/make.bat new file mode 100644 index 0000000..784d070 --- /dev/null +++ b/cores/curso/ch05/make.bat @@ -0,0 +1,12 @@ +SET speed=2 +SET ruta_ucf=ch05 +SET ruta_bat=..\..\ +call :genbitstream debounce_test +goto :eof + +:genbitstream +SET machine=%1 +call %ruta_bat%genxst.bat +call %ruta_bat%generar.bat v4 ZX1 +copy /y COREn.ZX1 %machine%.ZX1 +goto :eof diff --git a/cores/curso/ch05/timings.xcf b/cores/curso/ch05/timings.xcf new file mode 100644 index 0000000..7ce464f --- /dev/null +++ b/cores/curso/ch05/timings.xcf @@ -0,0 +1,2 @@ +# Timing constraints +NET "clk" PERIOD=20 ns;