diff --git a/cores/curso/ch03/make.bat b/cores/curso/ch03/make.bat index 48be00f..558c2cb 100644 --- a/cores/curso/ch03/make.bat +++ b/cores/curso/ch03/make.bat @@ -11,5 +11,5 @@ goto :eof SET machine=%1 call %ruta_bat%genxst.bat call %ruta_bat%generar.bat v4 ZX1 -copy /y COREn.ZX1 %ruta_bat%.ZX1 +copy /y COREn.ZX1 %machine%.ZX1 goto :eof diff --git a/cores/curso/ch04/ch04_zxuno_v4.ucf b/cores/curso/ch04/ch04_zxuno_v4.ucf new file mode 100644 index 0000000..617c55b --- /dev/null +++ b/cores/curso/ch04/ch04_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/ch04/debounce.vhd b/cores/curso/ch04/debounce.vhd new file mode 100644 index 0000000..3cad598 --- /dev/null +++ b/cores/curso/ch04/debounce.vhd @@ -0,0 +1,116 @@ +-- Listing 5.6 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity debounce is + port( + clk, reset: in std_logic; + sw: in std_logic; + db: out std_logic + ); +end debounce; + +architecture fsmd_arch of debounce 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 fsmd_arch; diff --git a/cores/curso/ch04/disp_mux_test.prj b/cores/curso/ch04/disp_mux_test.prj new file mode 100644 index 0000000..d2f2d71 --- /dev/null +++ b/cores/curso/ch04/disp_mux_test.prj @@ -0,0 +1,2 @@ +vhdl work "list_ch04_14_disp_test.vhd" +vhdl work "list_ch04_13_disp_mux.vhd" diff --git a/cores/curso/ch04/disp_mux_test.ut b/cores/curso/ch04/disp_mux_test.ut new file mode 100644 index 0000000..a9facca --- /dev/null +++ b/cores/curso/ch04/disp_mux_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/ch04/disp_mux_test.xst b/cores/curso/ch04/disp_mux_test.xst new file mode 100644 index 0000000..21ab9de --- /dev/null +++ b/cores/curso/ch04/disp_mux_test.xst @@ -0,0 +1,53 @@ +set -tmpdir "projnav.tmp" +set -xsthdpdir "xst" +run +-ifn disp_mux_test.prj +-infer_ramb8 No -loop_iteration_limit 32768 +-ofn disp_mux_test +-ofmt NGC +-p xc6slx9-2-tqg144 +-top disp_mux_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/ch04/hex_mux_test.prj b/cores/curso/ch04/hex_mux_test.prj new file mode 100644 index 0000000..2ebdae9 --- /dev/null +++ b/cores/curso/ch04/hex_mux_test.prj @@ -0,0 +1,2 @@ +vhdl work "list_ch04_16_hex_test.vhd" +vhdl work "list_ch04_15_disp_hex.vhd" diff --git a/cores/curso/ch04/hex_mux_test.ut b/cores/curso/ch04/hex_mux_test.ut new file mode 100644 index 0000000..a9facca --- /dev/null +++ b/cores/curso/ch04/hex_mux_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/ch04/hex_mux_test.xst b/cores/curso/ch04/hex_mux_test.xst new file mode 100644 index 0000000..3dc1977 --- /dev/null +++ b/cores/curso/ch04/hex_mux_test.xst @@ -0,0 +1,53 @@ +set -tmpdir "projnav.tmp" +set -xsthdpdir "xst" +run +-ifn hex_mux_test.prj +-infer_ramb8 No -loop_iteration_limit 32768 +-ofn hex_mux_test +-ofmt NGC +-p xc6slx9-2-tqg144 +-top hex_mux_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/ch04/list_ch04_01_dff.vhd b/cores/curso/ch04/list_ch04_01_dff.vhd new file mode 100644 index 0000000..3128b4c --- /dev/null +++ b/cores/curso/ch04/list_ch04_01_dff.vhd @@ -0,0 +1,20 @@ +-- Listing 4.1 +library ieee; +use ieee.std_logic_1164.all; +entity d_ff is + port( + clk: in std_logic; + d: in std_logic; + q: out std_logic + ); +end d_ff; + +architecture arch of d_ff is +begin + process(clk) + begin + if (clk'event and clk='1') then + q <= d; + end if; + end process; +end arch; diff --git a/cores/curso/ch04/list_ch04_02_dffr.vhd b/cores/curso/ch04/list_ch04_02_dffr.vhd new file mode 100644 index 0000000..9caa9f2 --- /dev/null +++ b/cores/curso/ch04/list_ch04_02_dffr.vhd @@ -0,0 +1,22 @@ +-- Listing 4.2 +library ieee; +use ieee.std_logic_1164.all; +entity d_ff_reset is + port( + clk, reset: in std_logic; + d: in std_logic; + q: out std_logic + ); +end d_ff_reset; + +architecture arch of d_ff_reset is +begin + process(clk,reset) + begin + if (reset='1') then + q <='0'; + elsif (clk'event and clk='1') then + q <= d; + end if; + end process; +end arch; diff --git a/cores/curso/ch04/list_ch04_03_04_dffen.vhd b/cores/curso/ch04/list_ch04_03_04_dffen.vhd new file mode 100644 index 0000000..157645f --- /dev/null +++ b/cores/curso/ch04/list_ch04_03_04_dffen.vhd @@ -0,0 +1,45 @@ +-- Listing 4.3 +library ieee; +use ieee.std_logic_1164.all; +entity d_ff_en is + port( + clk, reset: in std_logic; + en: in std_logic; + d: in std_logic; + q: out std_logic + ); +end d_ff_en; + +architecture arch of d_ff_en is +begin + process(clk,reset) + begin + if (reset='1') then + q <='0'; + elsif (clk'event and clk='1') then + if (en='1') then + q <= d; + end if; + end if; + end process; +end arch; + +-- Listing 4.4 +architecture two_seg_arch of d_ff_en is + signal r_reg, r_next: std_logic; +begin + -- D FF + process(clk,reset) + begin + if (reset='1') then + r_reg <='0'; + elsif (clk'event and clk='1') then + r_reg <= r_next; + end if; + end process; + -- next-state logic + r_next <= d when en ='1' else + r_reg; + -- output logic + q <= r_reg; +end two_seg_arch; diff --git a/cores/curso/ch04/list_ch04_05_reg.vhd b/cores/curso/ch04/list_ch04_05_reg.vhd new file mode 100644 index 0000000..762638e --- /dev/null +++ b/cores/curso/ch04/list_ch04_05_reg.vhd @@ -0,0 +1,22 @@ +-- Listing 4.5 +library ieee; +use ieee.std_logic_1164.all; +entity reg_reset is + port( + clk, reset: in std_logic; + d: in std_logic_vector(7 downto 0); + q: out std_logic_vector(7 downto 0) + ); +end reg_reset; + +architecture arch of reg_reset is +begin + process(clk,reset) + begin + if (reset='1') then + q <=(others=>'0'); + elsif (clk'event and clk='1') then + q <= d; + end if; + end process; +end arch; diff --git a/cores/curso/ch04/list_ch04_06_reg_file.vhd b/cores/curso/ch04/list_ch04_06_reg_file.vhd new file mode 100644 index 0000000..4e8c9a9 --- /dev/null +++ b/cores/curso/ch04/list_ch04_06_reg_file.vhd @@ -0,0 +1,36 @@ +-- Listing 4.6 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity reg_file is + generic( + B: integer:=8; -- number of bits + W: integer:=2 -- number of address bits + ); + port( + clk, reset: in std_logic; + wr_en: in std_logic; + w_addr, r_addr: in std_logic_vector (W-1 downto 0); + w_data: in std_logic_vector (B-1 downto 0); + r_data: out std_logic_vector (B-1 downto 0) + ); +end reg_file; + +architecture arch of reg_file is + type reg_file_type is array (2**W-1 downto 0) of + std_logic_vector(B-1 downto 0); + signal array_reg: reg_file_type; +begin + process(clk,reset) + begin + if (reset='1') then + array_reg <= (others=>(others=>'0')); + elsif (clk'event and clk='1') then + if wr_en='1' then + array_reg(to_integer(unsigned(w_addr))) <= w_data; + end if; + end if; + end process; + -- read port + r_data <= array_reg(to_integer(unsigned(r_addr))); +end arch; diff --git a/cores/curso/ch04/list_ch04_07_shift.vhd b/cores/curso/ch04/list_ch04_07_shift.vhd new file mode 100644 index 0000000..c8edba9 --- /dev/null +++ b/cores/curso/ch04/list_ch04_07_shift.vhd @@ -0,0 +1,30 @@ +-- Listing 4.7 +library ieee; +use ieee.std_logic_1164.all; +entity free_run_shift_reg is + generic(N: integer := 8); + port( + clk, reset: in std_logic; + s_in: in std_logic; + s_out: out std_logic + ); +end free_run_shift_reg; + +architecture arch of free_run_shift_reg is + signal r_reg: std_logic_vector(N-1 downto 0); + signal r_next: std_logic_vector(N-1 downto 0); +begin + -- register + process(clk,reset) + begin + if (reset='1') then + r_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + r_reg <= r_next; + end if; + end process; + -- next-state logic (shift right 1 bit) + r_next <= s_in & r_reg(N-1 downto 1); + -- output + s_out <= r_reg(0); +end arch; diff --git a/cores/curso/ch04/list_ch04_08_shift_u.vhd b/cores/curso/ch04/list_ch04_08_shift_u.vhd new file mode 100644 index 0000000..f39bf5f --- /dev/null +++ b/cores/curso/ch04/list_ch04_08_shift_u.vhd @@ -0,0 +1,36 @@ +-- Listing 4.8 +library ieee; +use ieee.std_logic_1164.all; +entity univ_shift_reg is + generic(N: integer := 8); + port( + clk, reset: in std_logic; + ctrl: in std_logic_vector(1 downto 0); + d: in std_logic_vector(N-1 downto 0); + q: out std_logic_vector(N-1 downto 0) + ); +end univ_shift_reg; + +architecture arch of univ_shift_reg is + signal r_reg: std_logic_vector(N-1 downto 0); + signal r_next: std_logic_vector(N-1 downto 0); +begin + -- register + process(clk,reset) + begin + if (reset='1') then + r_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + r_reg <= r_next; + end if; + end process; + -- next-state logic + with ctrl select + r_next <= + r_reg when "00", --no op + r_reg(N-2 downto 0) & d(0) when "01", --shift left; + d(N-1) & r_reg(N-1 downto 1) when "10", --shift right; + d when others; -- load + -- output + q <= r_reg; +end arch; diff --git a/cores/curso/ch04/list_ch04_09_bin.vhd b/cores/curso/ch04/list_ch04_09_bin.vhd new file mode 100644 index 0000000..127aa13 --- /dev/null +++ b/cores/curso/ch04/list_ch04_09_bin.vhd @@ -0,0 +1,32 @@ +-- Listing 4.9 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity free_run_bin_counter is + generic(N: integer := 8); + port( + clk, reset: in std_logic; + max_tick: out std_logic; + q: out std_logic_vector(N-1 downto 0) + ); +end free_run_bin_counter; + +architecture arch of free_run_bin_counter is + signal r_reg: unsigned(N-1 downto 0); + signal r_next: unsigned(N-1 downto 0); +begin + -- register + process(clk,reset) + begin + if (reset='1') then + r_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + r_reg <= r_next; + end if; + end process; + -- next-state logic + r_next <= r_reg + 1; + -- output logic + q <= std_logic_vector(r_reg); + max_tick <= '1' when r_reg=(2**N-1) else '0'; +end arch; diff --git a/cores/curso/ch04/list_ch04_10_bin_u.vhd b/cores/curso/ch04/list_ch04_10_bin_u.vhd new file mode 100644 index 0000000..ea20ecb --- /dev/null +++ b/cores/curso/ch04/list_ch04_10_bin_u.vhd @@ -0,0 +1,39 @@ +-- Listing 4.10 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity univ_bin_counter is + generic(N: integer := 8); + port( + clk, reset: in std_logic; + syn_clr, load, en, up: in std_logic; + d: in std_logic_vector(N-1 downto 0); + max_tick, min_tick: out std_logic; + q: out std_logic_vector(N-1 downto 0) + ); +end univ_bin_counter; + +architecture arch of univ_bin_counter is + signal r_reg: unsigned(N-1 downto 0); + signal r_next: unsigned(N-1 downto 0); +begin + -- register + process(clk,reset) + begin + if (reset='1') then + r_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + r_reg <= r_next; + end if; + end process; + -- next-state logic + r_next <= (others=>'0') when syn_clr='1' else + unsigned(d) when load='1' else + r_reg + 1 when en ='1' and up='1' else + r_reg - 1 when en ='1' and up='0' else + r_reg; + -- output logic + q <= std_logic_vector(r_reg); + max_tick <= '1' when r_reg=(2**N-1) else '0'; + min_tick <= '1' when r_reg=0 else '0'; +end arch; diff --git a/cores/curso/ch04/list_ch04_11_mod_m.vhd b/cores/curso/ch04/list_ch04_11_mod_m.vhd new file mode 100644 index 0000000..144eae4 --- /dev/null +++ b/cores/curso/ch04/list_ch04_11_mod_m.vhd @@ -0,0 +1,36 @@ +-- Listing 4.11 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity mod_m_counter is + generic( + N: integer := 4; -- number of bits + M: integer := 10 -- mod-M + ); + port( + clk, reset: in std_logic; + max_tick: out std_logic; + q: out std_logic_vector(N-1 downto 0) + ); +end mod_m_counter; + +architecture arch of mod_m_counter is + signal r_reg: unsigned(N-1 downto 0); + signal r_next: unsigned(N-1 downto 0); +begin + -- register + process(clk,reset) + begin + if (reset='1') then + r_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + r_reg <= r_next; + end if; + end process; + -- next-state logic + r_next <= (others=>'0') when r_reg=(M-1) else + r_reg + 1; + -- output logic + q <= std_logic_vector(r_reg); + max_tick <= '1' when r_reg=(M-1) else '0'; +end arch; diff --git a/cores/curso/ch04/list_ch04_12_bin_tb.vhd b/cores/curso/ch04/list_ch04_12_bin_tb.vhd new file mode 100644 index 0000000..7ffaec7 --- /dev/null +++ b/cores/curso/ch04/list_ch04_12_bin_tb.vhd @@ -0,0 +1,116 @@ +-- Listing 4.12 +library ieee; +use ieee.std_logic_1164.all; + +entity bin_counter_tb is +end bin_counter_tb; + +architecture arch of bin_counter_tb is + constant THREE: integer := 3; + constant T: time := 20 ns; -- clk period + signal clk, reset: std_logic; + signal syn_clr, load, en, up: std_logic; + signal d: std_logic_vector(THREE-1 downto 0); + signal max_tick, min_tick: std_logic; + signal q: std_logic_vector(THREE-1 downto 0); +begin + --************************** + -- instantiation + --************************** + counter_unit: entity work.univ_bin_counter(arch) + generic map(N=>THREE) + port map(clk=>clk, reset=>reset, syn_clr=>syn_clr, + load=>load, en=>en, up=>up, d=>d, + max_tick=>max_tick, min_tick=>min_tick, q=>q); + + --************************** + -- clock + --************************** + -- 20 ns clock running forever + process + begin + clk <= '0'; + wait for T/2; + clk <= '1'; + wait for T/2; + end process; + --************************** + -- reset + --************************** + -- reset asserted for T/2 + reset <= '1', '0' after T/2; + + --************************** + -- other stimulus + --************************** + process + begin + --************************** + -- initial input + --************************** + syn_clr <= '0'; + load <= '0'; + en <= '0'; + up <= '1'; -- count up + d <= (others=>'0'); + wait until falling_edge(clk); + wait until falling_edge(clk); + --************************** + -- test load + --************************** + load <= '1'; + d <= "011"; + wait until falling_edge(clk); + load <= '0'; + -- pause 2 clocks + wait until falling_edge(clk); + wait until falling_edge(clk); + --************************** + -- test syn_clear + --************************** + syn_clr <= '1'; -- clear + wait until falling_edge(clk); + syn_clr <= '0'; + --************************** + -- test up counter and pause + --************************** + en <= '1'; -- count + up <= '1'; + for i in 1 to 10 loop -- count 10 clocks + wait until falling_edge(clk); + end loop; + en <='0'; + wait until falling_edge(clk); + wait until falling_edge(clk); + en <='1'; + wait until falling_edge(clk); + wait until falling_edge(clk); + --************************** + -- test down counter + --************************** + up <= '0'; + for i in 1 to 10 loop -- run 10 clocks + wait until falling_edge(clk); + end loop; + --************************** + -- other wait conditions + --************************** + -- continue until q=2 + wait until q="010"; + wait until falling_edge(clk); + up <= '1'; + -- continue until min_tick changes value + wait on min_tick; + wait until falling_edge(clk); + up <= '0'; + wait for 4*T; -- wait for 80 ns + en <= '0'; + wait for 4*T; + --************************** + -- terminate simulation + --************************** + assert false + report "Simulation Completed" + severity failure; + end process ; +end arch; diff --git a/cores/curso/ch04/list_ch04_13_disp_mux.vhd b/cores/curso/ch04/list_ch04_13_disp_mux.vhd new file mode 100644 index 0000000..d13cefe --- /dev/null +++ b/cores/curso/ch04/list_ch04_13_disp_mux.vhd @@ -0,0 +1,55 @@ +-- Listing 4.13 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity disp_mux is + port( + clk, reset: in std_logic; + in3, in2, in1, in0: in std_logic_vector(6 downto 0); + point: in std_logic; + colon: in std_logic; + an: out std_logic_vector(3 downto 0); + sseg: out std_logic_vector(7 downto 0) + ); +end disp_mux ; + +architecture arch of disp_mux is + -- refreshing rate around 800 Hz (50MHz/2^16) + constant N: integer:=18; + signal q_reg, q_next: unsigned(N-1 downto 0); + signal sel: std_logic_vector(1 downto 0); +begin + -- register + process(clk,reset) + begin + if reset='1' then + q_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + q_reg <= q_next; + end if; + end process; + + -- next-state logic for the counter + q_next <= q_reg + 1; + + -- 2 MSBs of counter to control 4-to-1 multiplexing + -- and to generate active-low enable signal + sel <= std_logic_vector(q_reg(N-1 downto N-2)); + process(sel,in0,in1,in2,in3) + begin + case sel is + when "00" => + an <= "1110"; + sseg <= '1' & in0; + when "01" => + an <= "1101"; + sseg <= '1' & in1; + when "10" => + an <= "1011"; + sseg <= colon & in2; + when others => + an <= "0111"; + sseg <= point & in3; + end case; + end process; +end arch; diff --git a/cores/curso/ch04/list_ch04_14_disp_test.vhd b/cores/curso/ch04/list_ch04_14_disp_test.vhd new file mode 100644 index 0000000..6cd4e82 --- /dev/null +++ b/cores/curso/ch04/list_ch04_14_disp_test.vhd @@ -0,0 +1,49 @@ +-- Listing 4.14 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity disp_mux_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) + ); +end disp_mux_test; + +architecture arch of disp_mux_test is + signal d3_reg, d2_reg: std_logic_vector(6 downto 0); + signal d1_reg, d0_reg: std_logic_vector(6 downto 0); + signal btn : std_logic_vector(3 downto 0); +begin + + btn <= not bot(3 downto 0); + led <= not bot; + + disp_unit: entity work.disp_mux + port map( + clk=>clk, reset=>'0', + in3=>d3_reg, in2=>d2_reg, in1=>d1_reg, in0=>d0_reg, + point=>'1', colon=>'1', + an=>an, sseg=>sseg); + -- registers for 4 led patterns + process (clk) + begin + if (clk'event and clk='1') then + if (btn(3)='1') then + d3_reg <= sw(6 downto 0); + end if; + if (btn(2)='1') then + d2_reg <= sw(6 downto 0); + end if; + if (btn(1)='1') then + d1_reg <= sw(6 downto 0); + end if; + if (btn(0)='1') then + d0_reg <= sw(6 downto 0); + end if; + end if; + end process; +end arch; diff --git a/cores/curso/ch04/list_ch04_15_disp_hex.vhd b/cores/curso/ch04/list_ch04_15_disp_hex.vhd new file mode 100644 index 0000000..90a0e5e --- /dev/null +++ b/cores/curso/ch04/list_ch04_15_disp_hex.vhd @@ -0,0 +1,81 @@ +-- Listing 4.15 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity disp_hex_mux is + port( + clk, reset: in std_logic; + hex3, hex2, hex1, hex0: in std_logic_vector(3 downto 0); + point: in std_logic; + colon: in std_logic; + an: out std_logic_vector(3 downto 0); + sseg: out std_logic_vector(7 downto 0) + ); +end disp_hex_mux ; + +architecture arch of disp_hex_mux is + -- each 7-seg led enabled (2^18/4)*25 ns (40 ms) + constant N: integer:=18; + signal q_reg, q_next: unsigned(N-1 downto 0); + signal sel: std_logic_vector(1 downto 0); + signal hex: std_logic_vector(3 downto 0); + signal dp: std_logic; +begin + -- register + process(clk,reset) + begin + if reset='1' then + q_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + q_reg <= q_next; + end if; + end process; + + -- next-state logic for the counter + q_next <= q_reg + 1; + + -- 2 MSBs of counter to control 4-to-1 multiplexing + sel <= std_logic_vector(q_reg(N-1 downto N-2)); + process(sel,hex0,hex1,hex2,hex3,colon,point) + begin + case sel is + when "00" => + an <= "1110"; + hex <= hex0; + dp <= '1'; + when "01" => + an <= "1101"; + hex <= hex1; + dp <= '1'; + when "10" => + an <= "1011"; + hex <= hex2; + dp <= colon; + when others => + an <= "0111"; + hex <= hex3; + dp <= point; + end case; + end process; + -- hex-to-7-segment led decoding + with hex select + sseg(6 downto 0) <= + "0000001" when "0000", + "1001111" when "0001", + "0010010" when "0010", + "0000110" when "0011", + "1001100" when "0100", + "0100100" when "0101", + "0100000" when "0110", + "0001111" when "0111", + "0000000" when "1000", + "0000100" when "1001", + "0001000" when "1010", --a + "1100000" when "1011", --b + "0110001" when "1100", --c + "1000010" when "1101", --d + "0110000" when "1110", --e + "0111000" when others; --f + -- decimal point + sseg(7) <= dp; +end arch; diff --git a/cores/curso/ch04/list_ch04_16_hex_test.vhd b/cores/curso/ch04/list_ch04_16_hex_test.vhd new file mode 100644 index 0000000..4a817de --- /dev/null +++ b/cores/curso/ch04/list_ch04_16_hex_test.vhd @@ -0,0 +1,33 @@ +-- Listing 4.16 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity hex_mux_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) + ); +end hex_mux_test; + +architecture arch of hex_mux_test is + signal a, b: unsigned(7 downto 0); + signal sum: std_logic_vector(7 downto 0); +begin + + led <= not bot; + + disp_unit: entity work.disp_hex_mux + port map( + clk=>clk, reset=>'0', + hex3=>sum(7 downto 4), hex2=>sum(3 downto 0), + hex1=>sw(7 downto 4), hex0=>sw(3 downto 0), + point=>'1', colon=>'0', + an=>an, sseg=>sseg); + a <= "0000" & unsigned(sw(3 downto 0)); + b <= "0000" & unsigned(sw(7 downto 4)); + sum <= std_logic_vector(a + b); +end arch; diff --git a/cores/curso/ch04/make.bat b/cores/curso/ch04/make.bat new file mode 100644 index 0000000..6e3e2c4 --- /dev/null +++ b/cores/curso/ch04/make.bat @@ -0,0 +1,15 @@ +SET speed=2 +SET ruta_ucf=ch04 +SET ruta_bat=..\..\ +rem call :genbitstream disp_mux_test +call :genbitstream hex_mux_test +rem call :genbitstream shifter_test +rem call :genbitstream fp_adder_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/ch04/timings.xcf b/cores/curso/ch04/timings.xcf new file mode 100644 index 0000000..7ce464f --- /dev/null +++ b/cores/curso/ch04/timings.xcf @@ -0,0 +1,2 @@ +# Timing constraints +NET "clk" PERIOD=20 ns;