diff --git a/cores/curso/ch03/make.bat b/cores/curso/ch03/make.bat index 558c2cb..639430f 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 %machine%.ZX1 +copy /y COREn.ZX1 %ruta_ucf%_%machine%.ZX1 goto :eof diff --git a/cores/curso/ch04/make.bat b/cores/curso/ch04/make.bat index 1819d3c..b522d05 100644 --- a/cores/curso/ch04/make.bat +++ b/cores/curso/ch04/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 %machine%.ZX1 +copy /y COREn.ZX1 %ruta_ucf%_%machine%.ZX1 goto :eof diff --git a/cores/curso/ch05/ch05_zxuno_v4.ucf b/cores/curso/ch05/ch05_zxuno_v4.ucf index 617c55b..0408e7d 100644 --- a/cores/curso/ch05/ch05_zxuno_v4.ucf +++ b/cores/curso/ch05/ch05_zxuno_v4.ucf @@ -13,16 +13,6 @@ 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 #======================================================== diff --git a/cores/curso/ch05/debounce_test.prj b/cores/curso/ch05/debounce_test.prj index 5b120a4..6064f76 100644 --- a/cores/curso/ch05/debounce_test.prj +++ b/cores/curso/ch05/debounce_test.prj @@ -1,2 +1,3 @@ vhdl work "list_ch05_07_db_test.vhd" vhdl work "list_ch05_06_debounce.vhd" +vhdl work "../ch04/list_ch04_15_disp_hex.vhd" diff --git a/cores/curso/ch05/list_ch05_07_db_test.vhd b/cores/curso/ch05/list_ch05_07_db_test.vhd index 7749359..ab526bf 100644 --- a/cores/curso/ch05/list_ch05_07_db_test.vhd +++ b/cores/curso/ch05/list_ch05_07_db_test.vhd @@ -33,7 +33,8 @@ begin 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); + point=>'1', colon=>'0', + an=>an, sseg=>sseg); -- instantiate debouncing circuit db_unit: entity work.db_fsm(arch) port map( diff --git a/cores/curso/ch05/make.bat b/cores/curso/ch05/make.bat index 784d070..ba2783b 100644 --- a/cores/curso/ch05/make.bat +++ b/cores/curso/ch05/make.bat @@ -8,5 +8,5 @@ goto :eof SET machine=%1 call %ruta_bat%genxst.bat call %ruta_bat%generar.bat v4 ZX1 -copy /y COREn.ZX1 %machine%.ZX1 +copy /y COREn.ZX1 %ruta_ucf%_%machine%.ZX1 goto :eof diff --git a/cores/curso/ch06/ch06_zxuno_v4.ucf b/cores/curso/ch06/ch06_zxuno_v4.ucf new file mode 100644 index 0000000..0408e7d --- /dev/null +++ b/cores/curso/ch06/ch06_zxuno_v4.ucf @@ -0,0 +1,42 @@ +#======================================================== +# 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 + +#======================================================== +# 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/ch06/debounce_test.prj b/cores/curso/ch06/debounce_test.prj new file mode 100644 index 0000000..4fb2acf --- /dev/null +++ b/cores/curso/ch06/debounce_test.prj @@ -0,0 +1,2 @@ +vhdl work "list_ch06_03_db_test.vhd" +vhdl work "list_ch06_01_02_debounce.vhd" diff --git a/cores/curso/ch06/debounce_test.ut b/cores/curso/ch06/debounce_test.ut new file mode 100644 index 0000000..a9facca --- /dev/null +++ b/cores/curso/ch06/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/ch06/debounce_test.xst b/cores/curso/ch06/debounce_test.xst new file mode 100644 index 0000000..38bd824 --- /dev/null +++ b/cores/curso/ch06/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/ch06/list_ch06_01_02_debounce.vhd b/cores/curso/ch06/list_ch06_01_02_debounce.vhd new file mode 100644 index 0000000..9039e96 --- /dev/null +++ b/cores/curso/ch06/list_ch06_01_02_debounce.vhd @@ -0,0 +1,145 @@ +-- Listing 6.1 +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_level, db_tick: out std_logic + ); +end debounce ; + +architecture exp_fsmd_arch of debounce is + constant N: integer:=21; -- filter of 2^N * 20ns = 20ms + type state_type is (zero, wait0, one, wait1); + signal state_reg, state_next: state_type; + signal q_reg, q_next: unsigned(N-1 downto 0); + signal q_load, q_dec, q_zero: std_logic; +begin + -- FSMD state & data registers + process(clk,reset) + begin + if reset='1' then + state_reg <= zero; + q_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + state_reg <= state_next; + q_reg <= q_next; + end if; + end process; + + -- FSMD data path (counter) next-state logic + q_next <= (others=>'1') when q_load='1' else + q_reg - 1 when q_dec='1' else + q_reg; + q_zero <= '1' when q_next=0 else '0'; + + -- FSMD control path next-state logic + process(state_reg,sw,q_zero) + begin + q_load <= '0'; + q_dec <= '0'; + db_tick <= '0'; + state_next <= state_reg; + case state_reg is + when zero => + db_level <= '0'; + if (sw='1') then + state_next <= wait1; + q_load <= '1'; + end if; + when wait1=> + db_level <= '0'; + if (sw='1') then + q_dec <= '1'; + if (q_zero='1') then + state_next <= one; + db_tick <= '1'; + end if; + else -- sw='0' + state_next <= zero; + end if; + when one => + db_level <= '1'; + if (sw='0') then + state_next <= wait0; + q_load <= '1'; + end if; + when wait0=> + db_level <= '1'; + if (sw='0') then + q_dec <= '1'; + if (q_zero='1') then + state_next <= zero; + end if; + else -- sw='1' + state_next <= one; + end if; + end case; + end process; +end exp_fsmd_arch; + + + +-- Listing 6.2 +architecture fsmd_arch of debounce is + constant N: integer:=21; -- filter of 2^N * 20ns = 40ms + type state_type is (zero, wait0, one, wait1); + signal state_reg, state_next: state_type; + signal q_reg, q_next: unsigned(N-1 downto 0); +begin + -- FSMD state & data registers + process(clk,reset) + begin + if reset='1' then + state_reg <= zero; + q_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + state_reg <= state_next; + q_reg <= q_next; + end if; + end process; + -- next-state logic & data path functional units/routing + process(state_reg,q_reg,sw,q_next) + begin + state_next <= state_reg; + q_next <= q_reg; + db_tick <= '0'; + case state_reg is + when zero => + db_level <= '0'; + if (sw='1') then + state_next <= wait1; + q_next <= (others=>'1'); + end if; + when wait1=> + db_level <= '0'; + if (sw='1') then + q_next <= q_reg - 1; + if (q_next=0) then + state_next <= one; + db_tick <= '1'; + end if; + else -- sw='0' + state_next <= zero; + end if; + when one => + db_level <= '1'; + if (sw='0') then + state_next <= wait0; + q_next <= (others=>'1'); + end if; + when wait0=> + db_level <= '1'; + if (sw='0') then + q_next <= q_reg - 1; + if (q_next=0) then + state_next <= zero; + end if; + else -- sw='1' + state_next <= one; + end if; + end case; + end process; +end fsmd_arch; diff --git a/cores/curso/ch06/list_ch06_03_db_test.vhd b/cores/curso/ch06/list_ch06_03_db_test.vhd new file mode 100644 index 0000000..24d7b9c --- /dev/null +++ b/cores/curso/ch06/list_ch06_03_db_test.vhd @@ -0,0 +1,69 @@ +-- Listing 6.3 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity debounce_test is + port( + clk: in std_logic; + btn: in std_logic_vector(3 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 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: std_logic; + signal db_tick, btn_tick, clr: std_logic; +-- Listing 7.3 +begin + -- instantiate debouncing circuit + db_unit: entity work.debounce(fsmd_arch) + port map( + clk=>clk, reset=>'0', sw=>btn(1), + db_level=> open, db_tick=>db_tick + ); + -- instantiate hex display time-multiplxing 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 + ); + + --================================================= + -- edge detection circuit for un-debounced input + --================================================= + process(clk) + begin + if (clk'event and clk='1') then + btn_reg <= btn(1); + end if; + end process; + btn_tick <= (not btn_reg) and btn(1); + + --================================================= + -- 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; + -- counter output + b_count <= std_logic_vector(q1_reg); + d_count <= std_logic_vector(q0_reg); +end arch; diff --git a/cores/curso/ch06/list_ch06_04_fib.vhd b/cores/curso/ch06/list_ch06_04_fib.vhd new file mode 100644 index 0000000..34d1a35 --- /dev/null +++ b/cores/curso/ch06/list_ch06_04_fib.vhd @@ -0,0 +1,72 @@ +-- Listing 6.4 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity fib is + port( + clk, reset: in std_logic; + start: in std_logic; + i: in std_logic_vector(4 downto 0); + ready, done_tick: out std_logic; + f: out std_logic_vector(19 downto 0) + ); +end fib; + +architecture arch of fib is + type state_type is (idle,op,done); + signal state_reg, state_next: state_type; + signal t0_reg, t0_next, t1_reg, t1_next: unsigned(19 downto 0); + signal n_reg, n_next: unsigned(4 downto 0); +begin + -- fsmd state and data registers + process(clk,reset) + begin + if reset='1' then + state_reg <= idle; + t0_reg <= (others=>'0'); + t1_reg <= (others=>'0'); + n_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + state_reg <= state_next; + t0_reg <= t0_next; + t1_reg <= t1_next; + n_reg <= n_next; + end if; + end process; + -- fsmd next-state logic + process(state_reg,n_reg,t0_reg,t1_reg,start,i,n_next) + begin + ready <='0'; + done_tick <= '0'; + state_next <= state_reg; + t0_next <= t0_reg; + t1_next <= t1_reg; + n_next <= n_reg; + case state_reg is + when idle => + ready <= '1'; + if start='1' then + t0_next <= (others=>'0'); + t1_next <= (0=>'1', others=>'0'); + n_next <= unsigned(i); + state_next <= op; + end if; + when op => + if n_reg=0 then + t1_next <= (others=>'0'); + state_next <= done; + elsif n_reg=1 then + state_next <= done; + else + t1_next <= t1_reg + t0_reg; + t0_next <= t1_reg; + n_next <= n_reg - 1; + end if; + when done => + done_tick <= '1'; + state_next <= idle; + end case; + end process; + -- output + f <= std_logic_vector(t1_reg); +end arch; \ No newline at end of file diff --git a/cores/curso/ch06/list_ch06_05_div.vhd b/cores/curso/ch06/list_ch06_05_div.vhd new file mode 100644 index 0000000..d3d589d --- /dev/null +++ b/cores/curso/ch06/list_ch06_05_div.vhd @@ -0,0 +1,102 @@ +-- Listing 6.5 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity div is + generic( + W: integer:=8; + CBIT: integer:=4 -- CBIT=log2(W)+1 + ); + port( + clk, reset: in std_logic; + start: in std_logic; + dvsr, dvnd: in std_logic_vector(W-1 downto 0); + ready, done_tick: out std_logic; + quo, rmd: out std_logic_vector(W-1 downto 0) + ); +end div; + +architecture arch of div is + type state_type is (idle,op,last,done); + signal state_reg, state_next: state_type; + signal rh_reg, rh_next: unsigned(W-1 downto 0); + signal rl_reg, rl_next: std_logic_vector(W-1 downto 0); + signal rh_tmp: unsigned(W-1 downto 0); + signal d_reg, d_next: unsigned(W-1 downto 0); + signal n_reg, n_next: unsigned(CBIT-1 downto 0); + signal q_bit: std_logic; +begin + -- fsmd state and data registers + process(clk,reset) + begin + if reset='1' then + state_reg <= idle; + rh_reg <= (others=>'0'); + rl_reg <= (others=>'0'); + d_reg <= (others=>'0'); + n_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + state_reg <= state_next; + rh_reg <= rh_next; + rl_reg <= rl_next; + d_reg <= d_next; + n_reg <= n_next; + end if; + end process; + + -- fsmd next-state logic and data path logic + process(state_reg,n_reg,rh_reg,rl_reg,d_reg, + start,dvsr,dvnd,q_bit,rh_tmp,n_next) + begin + ready <='0'; + done_tick <= '0'; + state_next <= state_reg; + rh_next <= rh_reg; + rl_next <= rl_reg; + d_next <= d_reg; + n_next <= n_reg; + case state_reg is + when idle => + ready <= '1'; + if start='1' then + rh_next <= (others=>'0'); + rl_next <= dvnd; -- dividend + d_next <= unsigned(dvsr); -- divisor + n_next <= to_unsigned(W+1, CBIT); -- index + state_next <= op; + end if; + when op => + -- shift rh and rl left + rl_next <= rl_reg(W-2 downto 0) & q_bit; + rh_next <= rh_tmp(W-2 downto 0) & rl_reg(W-1); + --decrease index + n_next <= n_reg - 1; + if (n_next=1) then + state_next <= last; + end if; + when last => -- last iteration + rl_next <= rl_reg(W-2 downto 0) & q_bit; + rh_next <= rh_tmp; + state_next <= done; + when done => + state_next <= idle; + done_tick <= '1'; + end case; + end process; + + -- compare and subtract + process(rh_reg, d_reg) + begin + if rh_reg >= d_reg then + rh_tmp <= rh_reg - d_reg; + q_bit <= '1'; + else + rh_tmp <= rh_reg; + q_bit <= '0'; + end if; + end process; + + -- output + quo <= rl_reg; + rmd <= std_logic_vector(rh_reg); +end arch; \ No newline at end of file diff --git a/cores/curso/ch06/list_ch06_06_bcd.vhd b/cores/curso/ch06/list_ch06_06_bcd.vhd new file mode 100644 index 0000000..a5de71c --- /dev/null +++ b/cores/curso/ch06/list_ch06_06_bcd.vhd @@ -0,0 +1,107 @@ +-- Listing 6.6 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity bin2bcd is + port( + clk: in std_logic; + reset: in std_logic; + start: in std_logic; + bin: in std_logic_vector(12 downto 0); + ready, done_tick: out std_logic; + bcd3,bcd2,bcd1,bcd0: out std_logic_vector(3 downto 0) + ); +end bin2bcd ; + +architecture arch of bin2bcd is + type state_type is (idle, op, done); + signal state_reg, state_next: state_type; + signal p2s_reg, p2s_next: std_logic_vector(12 downto 0); + signal n_reg, n_next: unsigned(3 downto 0); + signal bcd3_reg,bcd2_reg,bcd1_reg,bcd0_reg: unsigned(3 downto 0); + signal bcd3_next,bcd2_next,bcd1_next,bcd0_next: unsigned(3 downto 0); + signal bcd3_tmp,bcd2_tmp,bcd1_tmp,bcd0_tmp: unsigned(3 downto 0); +begin + -- state and data registers + process (clk,reset) + begin + if reset='1' then + state_reg <= idle; + p2s_reg <= (others=>'0'); + n_reg <= (others=>'0'); + bcd3_reg <= (others=>'0'); + bcd2_reg <= (others=>'0'); + bcd1_reg <= (others=>'0'); + bcd0_reg <= (others=>'0'); + elsif (clk'event and clk='1') then + state_reg <= state_next; + p2s_reg <= p2s_next; + n_reg <= n_next; + bcd3_reg <= bcd3_next; + bcd2_reg <= bcd2_next; + bcd1_reg <= bcd1_next; + bcd0_reg <= bcd0_next; + end if; + end process; + + -- fsmd next-state logic / data path operations + process(state_reg,start,p2s_reg,n_reg,n_next,bin, + bcd0_reg,bcd1_reg,bcd2_reg,bcd3_reg, + bcd0_tmp,bcd1_tmp,bcd2_tmp,bcd3_tmp) + begin + state_next <= state_reg; + ready <= '0'; + done_tick <= '0'; + p2s_next <= p2s_reg; + bcd0_next <= bcd0_reg; + bcd1_next <= bcd1_reg; + bcd2_next <= bcd2_reg; + bcd3_next <= bcd3_reg; + n_next <= n_reg; + case state_reg is + when idle => + ready <= '1'; + if start='1' then + state_next <= op; + bcd3_next <= (others=>'0'); + bcd2_next <= (others=>'0'); + bcd1_next <= (others=>'0'); + bcd0_next <= (others=>'0'); + n_next <="1101"; -- index + p2s_next <= bin; -- input shift register + state_next <= op; + end if; + when op => + -- shift in binary bit + p2s_next <= p2s_reg(11 downto 0) & '0'; + -- shift 4 BCD digits + bcd0_next <= bcd0_tmp(2 downto 0) & p2s_reg(12); + bcd1_next <= bcd1_tmp(2 downto 0) & bcd0_tmp(3); + bcd2_next <= bcd2_tmp(2 downto 0) & bcd1_tmp(3); + bcd3_next <= bcd3_tmp(2 downto 0) & bcd2_tmp(3); + n_next <= n_reg - 1; + if (n_next=0) then + state_next <= done; + end if; + when done => + state_next <= idle; + done_tick <= '1'; + end case; + end process; + + -- data path function units + bcd0_tmp <= bcd0_reg + 3 when bcd0_reg > 4 else + bcd0_reg; + bcd1_tmp <= bcd1_reg + 3 when bcd1_reg > 4 else + bcd1_reg; + bcd2_tmp <= bcd2_reg + 3 when bcd2_reg > 4 else + bcd2_reg; + bcd3_tmp <= bcd3_reg + 3 when bcd3_reg > 4 else + bcd3_reg; + + -- output + bcd0 <= std_logic_vector(bcd0_reg); + bcd1 <= std_logic_vector(bcd1_reg); + bcd2 <= std_logic_vector(bcd2_reg); + bcd3 <= std_logic_vector(bcd3_reg); +end arch; diff --git a/cores/curso/ch06/list_ch06_07_period.vhd b/cores/curso/ch06/list_ch06_07_period.vhd new file mode 100644 index 0000000..0d3cf1f --- /dev/null +++ b/cores/curso/ch06/list_ch06_07_period.vhd @@ -0,0 +1,77 @@ +-- Listing 6.7 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity period_counter is + port( + clk, reset: in std_logic; + start, si: in std_logic; + ready, done_tick: out std_logic; + prd: out std_logic_vector(9 downto 0) + ); +end period_counter; + +architecture arch of period_counter is + constant CLK_MS_COUNT: integer := 5; -- 50000; -- 1 ms tick + type state_type is (idle, waite, count, done); + signal state_reg, state_next: state_type; + signal t_reg, t_next: unsigned(15 downto 0); -- up to 50000 + signal p_reg, p_next: unsigned(9 downto 0); -- up to 1 sec + signal delay_reg: std_logic; + signal edge: std_logic; +begin + -- state and data register + process(clk,reset) + begin + if reset='1' then + state_reg <= idle; + t_reg <= (others=>'0'); + p_reg <= (others=>'0'); + delay_reg <= '0'; + elsif (clk'event and clk='1') then + state_reg <= state_next; + t_reg <= t_next; + p_reg <= p_next; + delay_reg <= si; + end if; + end process; + + edge <= (not delay_reg) and si; + + process(start,edge,state_reg,t_reg,t_next,p_reg) + begin + ready <= '0'; + done_tick <= '0'; + state_next <= state_reg; + p_next <= p_reg; + t_next <= t_reg; + case state_reg is + when idle => + ready <= '1'; + if (start='1') then + state_next <= waite; + end if; + when waite => -- wait for the first edge + if (edge='1') then + state_next <= count; + t_next <= (others=>'0'); + p_next <= (others=>'0'); + end if; + when count => + if (edge='1') then -- 2nd edge arrived + state_next <= done; + else -- otherwise count + if t_reg = CLK_MS_COUNT-1 then -- 1ms tick + t_next <= (others=>'0'); + p_next <= p_reg + 1; + else + t_next <= t_reg + 1; + end if; + end if; + when done => + done_tick <= '1'; + state_next <= idle; + end case; + end process; + prd <= std_logic_vector(p_reg); +end arch; diff --git a/cores/curso/ch06/list_ch06_08_slow_freq.vhd b/cores/curso/ch06/list_ch06_08_slow_freq.vhd new file mode 100644 index 0000000..1343072 --- /dev/null +++ b/cores/curso/ch06/list_ch06_08_slow_freq.vhd @@ -0,0 +1,87 @@ +-- Listing 6.8 +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +entity low_freq_counter is + port( + clk, reset: in std_logic; + start: in std_logic; + si: in std_logic; + bcd3, bcd2, bcd1, bcd0: out std_logic_vector(3 downto 0) + ); +end low_freq_counter; + +architecture arch of low_freq_counter is + type state_type is (idle, count, frq, b2b); + signal state_reg, state_next: state_type; + signal prd: std_logic_vector(9 downto 0); + signal dvsr, dvnd, quo: std_logic_vector(19 downto 0); + signal prd_start, div_start, b2b_start: std_logic; + signal prd_done_tick, div_done_tick, b2b_done_tick: std_logic; +begin + --=============================================== + -- component instantiation + --=============================================== + -- instantiate period counter + prd_count_unit: entity work.period_counter + port map(clk=>clk, reset=>reset, start=>prd_start, si=>si, + ready=>open, done_tick=>prd_done_tick, prd=>prd); + -- instantiate division circuit + div_unit: entity work.div + generic map(W=>20, CBIT=>5) + port map(clk=>clk, reset=>reset, start=>div_start, + dvsr=>dvsr, dvnd=>dvnd, quo=>quo, rmd=>open, + ready=>open, done_tick=>div_done_tick); + -- instantiate binary-to-BCD convertor + bin2bcd_unit: entity work.bin2bcd + port map + (clk=>clk, reset=>reset, start=>b2b_start, + bin=>quo(12 downto 0), ready=>open, + done_tick=>b2b_done_tick, + bcd3=>bcd3, bcd2=>bcd2, bcd1=>bcd1, bcd0=>bcd0); + -- signal width extension + dvnd <= std_logic_vector(to_unsigned(1000000, 20)); + dvsr <= "0000000000" & prd; + + --=============================================== + -- Master FSM + --=============================================== + process(clk,reset) + begin + if reset='1' then + state_reg <= idle; + elsif (clk'event and clk='1') then + state_reg <= state_next; + end if; + end process; + + process(state_reg,start, + prd_done_tick,div_done_tick,b2b_done_tick) + begin + state_next <= state_reg; + prd_start <='0'; + div_start <='0'; + b2b_start <='0'; + case state_reg is + when idle => + if start='1' then + state_next <= count; + prd_start <='1'; + end if; + when count => + if (prd_done_tick='1') then + div_start <='1'; + state_next <= frq; + end if; + when frq => + if (div_done_tick='1') then + b2b_start <='1'; + state_next <= b2b; + end if; + when b2b => + if (b2b_done_tick='1') then + state_next <= idle; + end if; + end case; + end process; +end arch; diff --git a/cores/curso/ch06/make.bat b/cores/curso/ch06/make.bat new file mode 100644 index 0000000..5055b58 --- /dev/null +++ b/cores/curso/ch06/make.bat @@ -0,0 +1,12 @@ +SET speed=2 +SET ruta_ucf=ch06 +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 %ruta_ucf%_%machine%.ZX1 +goto :eof diff --git a/cores/curso/ch06/timings.xcf b/cores/curso/ch06/timings.xcf new file mode 100644 index 0000000..7ce464f --- /dev/null +++ b/cores/curso/ch06/timings.xcf @@ -0,0 +1,2 @@ +# Timing constraints +NET "clk" PERIOD=20 ns;