未经作者允许,请勿发布该文 档! yingqichen@sjtu.edu.cn VHDL Simulation & Synthesis CPU.vhd (Simple Behavior Model) LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE work.bv_math.ALL; USE work.cpu8pac.ALL; ENTITY cpu IS ... END cpu; ARCHITECTURE version1 OF cpu IS BEGIN clock_gen : PROCESS BEGIN ... END PROCESS; main_sequence : PROCESS BEGIN IF reset = '1' THEN --initialisation ... ELSE --fetch instruction ... --increment program counter ... --execute CASE inst_reg IS WHEN add => acca := acca + accb; WHEN subr => acca := acca - accb; ... ... END CASE; END IF; END PROCESS main_sequence; END version1; CPU.vhd (Diagram) memrd reset CPU memwr pc address pc Program counter acca accb Register of ALU inst_reg Store Instruction mar Store Operator acca accb inst_reg mar data CPU Clock Generate Reset Instruction Processing Fetch Instruction From Memory Analysis & Execute Instruction Simple Arithmetic Operation Data Transfer Operation Jump Instruction CPU Structure Clock Generate Reset Instruction Processing Fetch Instruction From Memory Incensement Program Counter Analysis & Execute Instruction Simple Arithmetic Operation Data Transfer Operation Jump Instruction LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE work.bv_math.ALL; USE work.cpu8pac.ALL; ENTITY cpu IS ... END cpu; ARCHITECTURE version1 OF cpu IS BEGIN clock_gen : PROCESS BEGIN ... END PROCESS; main_sequence : PROCESS BEGIN IF reset = '1' THEN --initialisation ... ELSE --fetch instruction ... --increment program counter ... --execute CASE inst_reg IS WHEN add => acca := acca + accb; WHEN subr => acca := acca - accb; ... ... END CASE; END IF; END PROCESS main_sequence; END version1; Clock Generator clock_gen : PROCESS BEGIN clock <= '1','0' AFTER cycle_time/2; WAIT FOR cycle_time; END PROCESS; cycle_time/2 cycle_time/2 Reset IF reset = '1' THEN memrd <= '1'; memwr <= '1'; pc := (OTHERS => '0'); address <= (OTHERS => 'Z'); data <= (OTHERS => 'Z'); WAIT UNTIL rising_edge(clock); ELSE … Fetch Instruction & increase PC --fetch phase address <= To_StdlogicVector(pc); clock WAIT FOR cycle_time/4; memrd <= '0'; address WAIT FOR cycle_time/2; memrd <= '1'; data --read instruction inst_reg := To_bitvector(data(7 DOWNTO 4)); --load page address memrd mar(11 DOWNTO 8) := To_bitvector(data(3 DOWNTO 0)); --increment program counter pc := inc_bv(pc); --wait until end of cycle WAIT UNTIL rising_edge(clock); Page address (will be used in load/store instruction) Read inst_reg, mar(11~8), increase pc at this monent Execute Instruction (Arithmetic Instruction) --execute CASE inst_reg IS WHEN add => acca := acca + accb; -- add WHEN subr => acca := acca - accb; -- subtraction WHEN inc => acca := inc_bv(acca); -- increment WHEN dec => acca := dec_bv(acca); -- decrement WHEN land => acca := acca AND accb; -- logical and WHEN lor => acca := acca OR accb; -- logical or WHEN cmp => acca := NOT acca; -- complement WHEN lxor => acca := acca XOR accb; -- logical xor WHEN lita => acca := acca; -- ??? WHEN litb => acca := accb; -WHEN clra => acca := (OTHERS => '0'); -- Clear to acca 0 WHEN … Execute Instruction (Load & Store Instruction) Get address offset (page address mar(8~11) is got in the fetching instruction step) WHEN lda|ldb|sta|stb => ELSE address <= To_StdlogicVector(pc); WAIT FOR cycle_time/8; WAIT FOR cycle_time/4; IF inst_reg = sta THEN memrd <= '0'; --ouput data WAIT FOR cycle_time/2; data <= To_StdlogicVector(acca); memrd <= '1'; ELSE --read page offset address --ouput data mar(7 DOWNTO 0) := To_bitvector(data); data <= To_StdlogicVector(accb); --increment program counter END IF; pc := inc_bv(pc); WAIT FOR cycle_time/8; --wait until end of cycle memwr <= '0'; WAIT UNTIL rising_edge(clock); WAIT FOR cycle_time/2; --output address of operand memwr <= '1'; address <= To_StdlogicVector(mar); WAIT FOR cycle_time/8; IF ((inst_reg = lda) OR (inst_reg = ldb)) data <= (OTHERS => 'Z'); THEN --wait until end of cycle WAIT FOR cycle_time/4; WAIT UNTIL rising_edge(clock); memrd <= '0'; END IF; WAIT FOR cycle_time/2; WHEN jmp => memrd <= '1'; … IF inst_reg = lda THEN --load accumulator a from bus acca := To_bitvector(data); ELSE --load accumulator b from bus accb := To_bitvector(data); END IF; --wait until end of cycle WAIT UNTIL rising_edge(clock); Execute Instruction (Load & Store Instruction Waveform) clock clock Address Address data data memrd memrd pc mar acca bcca mar pc Load Store acca bcca Jump Instruction WHEN jmp => address <= To_StdlogicVector(pc); --transfer page address to pc from mar pc(11 DOWNTO 8) := mar(11 DOWNTO 8); --read in offset address WAIT FOR cycle_time/4; Update high 4 bits memrd <= '0'; using mar (value in WAIT FOR cycle_time/2; mar is the jump page memrd <= '1'; address) pc(7 DOWNTO 0) := To_bitvector(data); --wait until end of cycle WAIT UNTIL rising_edge(clock); Update low 8 bits END CASE; using the value on END IF; the data bus 8051 Design File Origination Top File Test Platform 8051 Modules Key Feature Fully synchronous design Instruction set compatible to the industry standard 8051 microcontroller Optimized architecture enables fast one to four clocks per OP code Up to 10 times faster due to completely new architecture User selectable number of timers/counters as well as serial interface units Active timer/counter and serial interface units selectable via additional special function register Optional implementation of the multiply command (MUL) using a parallel multiplier unit Optional implementation of the divide command (DIV) using a parallel divider unit Optional implementation of the decimal adjustment command (DA) No multiplexed I/O ports 256 bytes internal RAM, up to 64 Kbytes ROM and up to 64 Kbytes RAM Source code available free of charge under the GNU LGPL license Technology independent, clear structured, well commented VHDL source code Easily expandable by adapting/changing VHDL source code Parameterizeable via VHDL constants 8051 Diagram Ports Definitions Directory Docu Mism document Modelsim Files Mc8051_compile.do Script to compile vhdl code under Modelsim Mc8051_sim.do Script to simulate the model in Modelsim Synpl Mc8051_core.prj Tb Vhdl Project file for Synpilfy Test bench files vhdl design files File Name in dir ‘vhdl’ Xxxxxxxx_.vhd Entity definition Xxxxxxxx_struc.vhd Structure architecture model, all “port map” clauses Xxxxxxxx_rtl.vhd RTL architecture model Xxxxxxxx_cfg.vhd Configuration file Design Hierarchy mc8051_top_struc.vhd architecture struc of mc8051_top is begin i_mc8051_core : mc8051_core port map( ... ); i_mc8051_ram : mc8051_ram port map ( ... ); i_mc8051_rom : mc8051_rom port map ( ... ); i_mc8051_ramx : mc8051_ramx port map ( ... ); end struc; mc8051_top_struc.vhd (Block Diagram) mc8051_control_struc.vhd Ram (Entity) library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; ------------------------ ENTITY DECLARATION ------------------------entity mc8051_ram is port (clk : in std_logic; -- clock signal reset : in std_logic; -- reset signal ram_data_i : in std_logic_vector(7 downto 0); -- data input ram_data_o : out std_logic_vector(7 downto 0); -- data output ram_adr_i : in std_logic_vector(6 downto 0); -- adresses ram_wr_i : in std_logic; -- read=0, write=1 ram_en_i : in std_logic); -- inactive=0;active=1 end mc8051_ram; Ram Block Diagram ram_adr_i ram_adr_i integer ram_data_o … clk reset ram_wr_i ram_en_i ram_data_i Ram (Read) architecture sim of mc8051_ram is type ram_type is array (127 downto 0) of unsigned(7 downto 0); signal gpram: ram_type; -- general purpose RAM begin ---------- ram_read ---------p_read : process (clk, reset) begin if reset='1' then ram_data_o <= "00000000"; else if Rising_Edge(clk) then ram_data_o <= std_logic_vector(gpram(conv_integer(unsigned(ram_adr_i)))); end if; end if; end process p_read; Ram (Write) ---------- ram_write ---------p_write : process (clk, reset, ram_en_i) begin if reset='1' then gpram <= (others => (others =>'0')); -- reset every bit else if Rising_Edge(clk) then if ((ram_en_i='1') and (ram_wr_i='1')) then gpram(conv_integer(unsigned(ram_adr_i))) <= unsigned(ram_data_i); end if; end if; end if; end process p_write; end sim; Ramx (Entity) library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; ------------------------ ENTITY DECLARATION ------------------------entity mc8051_ramx is port (clk : in std_logic; -- clock signal reset : in std_logic; -- reset signal ram_data_i : in std_logic_vector(7 downto 0); -- data input ram_data_o : out std_logic_vector(7 downto 0); -- data output ram_adr_i : in std_logic_vector(15 downto 0); -- adresses ram_wr_i : in std_logic); -- read=0, write=1 end mc8051_ramx; Ramx (Architecture) architecture sim of mc8051_ramx is type ram_type is array (65535 downto 0) of bit_vector(7 downto 0); begin p_readwrite : process (clk, reset) variable gpram: ram_type; -- general purpose RAM begin if reset='1' then ram_data_o <= "00000000"; gpram := (others => (others =>'0')); -- reset every bit else if Rising_Edge(clk) then ram_data_o <= to_stdlogicvector(gpram(conv_integer(unsigned(ram_adr_i)))); if ram_wr_i='1' then gpram(conv_integer(unsigned(ram_adr_i))) := to_bitvector(ram_data_i); end if; end if; end if; end process p_readwrite; end sim; Rom (Entity) library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_textio.all; library STD; use STD.textio.all; ------------------------ ENTITY DECLARATION ------------------------entity mc8051_rom is generic (c_init_file : string := "mc8051_rom.dua"); port (clk : in std_logic; -- clock signal reset : in std_logic; -- reset signal rom_data_o : out std_logic_vector(7 downto 0); -- data output rom_adr_i : in std_logic_vector(15 downto 0)); -- adresses end mc8051_rom; Ram Block Diagram rom_adr_i rom_en_i rom_data_o … clk reset rom_adr_i integer Rom (Architecture) architecture sim of mc8051_rom is type rom_type is array (65535 downto 0) of bit_vector(7 downto 0); signal s_init : boolean := false; Begin ---------- rom_read ---------p_read : process (clk, reset, rom_adr_i) variable v_loop : integer; variable v_line : line; variable v_rom_data : rom_type; file f_initfile : text is in c_init_file; begin if (not s_init) then v_loop := 0; while ((not endfile(f_initfile) and (v_loop < 65535))) loop readline(f_initfile,v_line); read(v_line,v_rom_data(v_loop)); v_loop := v_loop + 1; end loop; s_init <= true; end if; if (clk'event and (clk = '1')) then -- rising clock edge rom_data_o <= to_stdlogicvector(v_rom_data(conv_integer(unsigned(rom_adr_i)))); end if; end process p_read; end sim; architecture sim of tb_mc8051_top is function FUNC_PULLUP (signal s_bidir_line : in std_logic) return std_logic is … -- system clock definition end FUNC_PULLUP; p_clock : process begin variable v_loop1 : integer; i_mc8051_top : mc8051_top begin port map (…); clk <= '0'; gen_portmodel : for i in 0 to 7 generate wait for one_period/2; … while true loop end generate; clk <= not clk; p_run : process wait for one_period/2; end loop; begin end process p_clock; … -------------------------------------reset <= '1'; wait for one_period + one_period/2 + 5 ns; end sim; reset <= '0'; wait for one_period * 5000; wait for one_period / 2; assert false report "END OF SIMULATION" severity failure; end process p_run; Testbench Test Bench ROM CPU Reset Clock RAM Configurable Mudules -----------------------------------------------mc8051_p.vhd ------------------------------ Select how many timer/counter units should be implemented -- Default: 1 constant C_IMPL_N_TMR : integer := 1; -------------------------------------------------------------------------------------------------------------------------------------------------------- Select how many serial interface units should be implemented -- Default: C_IMPL_N_TMR ---(DO NOT CHANGE!)--constant C_IMPL_N_SIU : integer := C_IMPL_N_TMR; -------------------------------------------------------------------------------------------------------------------------------------------------------- Select how many external interrupt-inputs should be implemented -- Default: C_IMPL_N_TMR ---(DO NOT CHANGE!)--- Configurable Modules (contd.) entity control_mem is port { … all_tcon_tr0_o : out std_logic_vector(C_IMPL_N_TMR-1 downto 0); }; Use constant instead of Generic … architecture rtl of control_mem is … for_tmr: for i in 0 to C_IMPL_N_TMR-1 generate … end generate for_tmr; end rtl; Configurable Modules (contd.) for i in 0 to C_IMPL_N_TMR-1 loop … end loop; type t_tmr_lv is array(C_IMPL_N_TMR-1 downto 0) of std_logic_vector(7 downto 0); Select Timer / Counter Using TSEL to select which module to use mc8051_alu_struc.vhd ADDSUB_CORE one carry, one auxiliary-carry Half carry bit, so the 8-bit adder will e implemented by 2 4-bit adder Addsub_cy & addsub_ovcy Module addsub_cy architecture rtl of addsub_cy is begin p_addsub: process (opa_i, opb_i, addsub_i, cy_i) variable v_a : unsigned(DWIDTH downto 0); variable v_b : unsigned(DWIDTH downto 0); variable v_result : std_logic_vector(DWIDTH+1 downto 0); begin -- process p_addsub v_a(DWIDTH downto 1) := unsigned(opa_i); v_b(DWIDTH downto 1) := unsigned(opb_i); if addsub_i = '1' then -- add or sub v_a(0) := '1'; v_b(0) := cy_i; 0/1 opa_i opb_i cy_o rslt_o v_result := conv_unsigned(v_a,DWIDTH+2) + v_b; -- add operation else v_a(0) := '0'; v_b(0) := cy_i; So that the “+” function will get a sum 1 bit longer v_result := conv_unsigned(v_a,DWIDTH+2) - v_b; -- sub operation end if; cy_o <= v_result(DWIDTH+1); rslt_o <= v_result(DWIDTH downto 1); end process p_addsub; end rtl; cy_i Append an extra bit to handle carry Module sddsub_ovcy architecture rtl of addsub_ovcy is begin gen_greater_one: if (DWIDTH > 1) generate else v_a(0) := '0'; p_addsub_ov: process (opa_i, opb_i, addsub_i, cy_i) v_b(0) := cy_i; variable v_a : unsigned(DWIDTH-1 downto 0); v_result := conv_unsigned(v_a,DWIDTH+1) - unsigned(v_b); variable v_b : unsigned(DWIDTH-1 downto 0); v_la(0) := '0'; variable v_result : std_logic_vector(DWIDTH downto 0); v_lb(0) := v_result(DWIDTH); variable v_la : unsigned(1 downto 0); v_lresult := conv_unsigned(v_la,3) - unsigned(v_lb); variable v_lb : unsigned(1 downto 0); end if; variable v_lresult : std_logic_vector(2 downto 0); cy_o <= v_lresult(2); begin -- process p_addsub ov_o <= (v_result(DWIDTH) and not(v_lresult(2))) or v_a(DWIDTH-1 downto 1) := unsigned(opa_i(DWIDTH-2 downto 0)); (v_lresult(2) and not(v_result(DWIDTH))); v_b(DWIDTH-1 downto 1) := unsigned(opb_i(DWIDTH-2 downto 0)); rslt_o(DWIDTH-2 downto 0) <= v_result(DWIDTH-1 downto 1); v_la(1) := opa_i(DWIDTH-1); rslt_o(DWIDTH-1) <= v_lresult(1); end process p_addsub_ov; v_lb(1) := opb_i(DWIDTH-1); end generate gen_greater_one; if addsub_i = '1' then opa_i(2:0) end rtl; 0/1 v_a(0) := '1'; The add operation is separate into 2, add of bit2~0 and add of bit 3. The separation of add operation help find overflow opa_i(3) opb_i (2:0) opb_i (3) v_b(0) := cy_i; v_result := conv_unsigned(v_a,DWIDTH+1) + unsigned(v_b); v_la(0) := '1'; v_lb(0) := v_result(DWIDTH); v_lresult := conv_unsigned(v_la,3) + unsigned(v_lb); Carry out from bit 7 cy_i Carry out from bit 6 architecture rtl of alucore is constant LAND : std_logic_vector(3 downto 0) := "0011"; constant LOR : std_logic_vector(3 downto 0) := "0101"; constant LXOR : std_logic_vector(3 downto 0) := "0110"; constant RL : std_logic_vector(3 downto 0) := "0111"; … … begin -- architecture structural p_alu: process (alu_cmd_i, op_a_i, op_b_i, cy_i) begin case alu_cmd_i is ----------------------------------------------------------when LAND => -- op_a_i and op_b_i result_o <= op_a_i and op_b_i; cy_o <= cy_i; ----------------------------------------------------------when LOR => -- op_a_i or op_b_i result_o <= op_a_i or op_b_i; cy_o <= cy_i; ----------------------------------------------------------when LXOR => -- op_a_i xor op_b_i result_o <= op_a_i xor op_b_i; cy_o <= cy_i; ----------------------------------------------------------… end case; end process p_alu; end rtl; ALU Module ALUMUX Module Connect wires according to different input instruction ALUMUX addsub_core alucore dcml_adjust comb_divider comb_mltplr architecture rtl of alumux is constant DA : std_logic_vector(5 downto 0) := "100000"; constant ADD_ACC_RAM : std_logic_vector(5 downto 0) := "100001"; constant AND_ACC_RAM : std_logic_vector(5 downto 0) := "100101"; ... Begin process (…) begin case cmd_i is when AND_ACC_RAM => alu_cmd_o <= LAND; op_a_o <= acc_i; op_b_o <= ram_data_i; when AND_ACC_ROM => ...; end case; ALUMUX Module (VHDL) … end process; end rtl; Timer / Counter Mc8051_tmrctr_rtl.vhd Code structure Clk/16 Falling Edge Detection & Synchronize Timer/Counter 0 Falling Edge Detection & Synchronize Timer/Counter 1 Mode 0 Timer/Counter 0 Mode 0 Timer/Counter 1 Mode 1 Timer/Counter 0 Mode 1 Timer/Counter 1 Mode 2 Timer/Counter 0 Mode 2 Timer/Counter 1 Mode 3 Timer/Counter 0 Mode 3 Timer/Counter 1 Timer / Counter (clock) s_count_enable <= '1' when s_pre_count = conv_unsigned(15,4) else '0'; p_divide_clk: process (clk, reset) begin if reset = '1' then s_pre_count <= conv_unsigned(0,4); else if clk'event and clk='1' then s_pre_count <= s_pre_count + conv_unsigned(1,1); end if; Conv_unsigned(value, bit_length) end if; end process p_divide_clk; Clk16 Timer / Counter (edge detection) s_ext_edge0 <= '1' when (s_t0ff1 = '0' and s_t0ff2 = '1') else '0'; p_sample_t0: process (clk, reset) begin if reset = '1' then s_t0ff0 <= '0'; s_t0ff1 <= '0'; s_t0ff2 <= '0'; else if clk'event and clk = '1' then if s_pre_count = conv_unsigned(6,3) then if s_c_t0 = '1' then s_t0ff0 <= t0_i; s_t0ff1 <= s_t0ff0; s_t0ff2 <= s_t0ff1; t0_i s_t0ff0 s_t0ff1 end if; end if; end if; D Q D Q D end if; end process p_sample_t0; CLK CLK s_ext_edge0 s_t0ff2 CLK Q Timer / Counter (VHDL Structure) case s_mode0 is Mode 0 when "00" => ...; when "01" => ...; when "10" => ...; when "11" => ...; when others => null; end case; Mode 1 Mode 2 Mode 3 Timer / Counter (TCON) Timer / Counter (TMOD) Mode 0, 13-bit Timer Clock/16 if s_tmr_ctr0_en = '1' then if s_count_enable = '1' then if s_c_t0 = '0' or (s_ext_edge0 = '1' and s_c_t0 = '1') then if s_count0 = conv_unsigned(8191,16) then s_tf0 <= '1'; 13 - 1 8191 = 2 else s_tf0 <= '0'; end if; end if; end if; end if; Mode 0, 13-bit Timer (contd.) Reload low 8 bit Reload low bits if wt_i = "00" and wt_en_i = '1' then if wt_i = "10" and wt_en_i = '1' then Clock/16 s_countl0 <= unsigned(reload_i); s_counth0 <= unsigned(reload_i); Higher bits else counts when Timer mode or Counter mode? else if s_tmr_ctr0_en = '1' then if s_tmr_ctr0_en = '1' then low bits if s_count_enable = '1' then if s_count_enable = '1' then count to 255 if s_c_t0 = '0' then if s_c_t0 = '0' then if s_count0 = conv_unsigned(8191,16) then if s_count0 = conv_unsigned(8191,16) then s_counth0 <= conv_unsigned(0,8); s_countl0 <= conv_unsigned(0,8); else else if s_countl0 = conv_unsigned(255,8) then s_countl0 <= s_countl0 + conv_unsigned(1,1); s_counth0 <= s_counth0 + conv_unsigned(1,1); end if; end if; end if; else else if s_ext_edge0 = '1' then if s_ext_edge0 = '1' then if s_count0 = conv_unsigned(8191,16) then if s_count0 = conv_unsigned(8191,16) then s_countl0 <= conv_unsigned(0,8); s_counth0 <= conv_unsigned(0,8); else else s_countl0 <= s_countl0 + conv_unsigned(1,1); if s_countl0 = conv_unsigned(255,8) then s_counth0 <= s_counth0 + conv_unsigned(1,1); end if; end if; end if; end if; end if; end if; end if; end if; end if; end if; end if; end if; end if; Mode 1, 16-bit Timer Clock/16 if s_tmr_ctr0_en = '1' then if s_count_enable = '1' then if s_c_t0 = '0' or (s_ext_edge0 = '1' and s_c_t0 = '1') then if s_count0 = conv_unsigned(65535,16) then s_tf0 <= '1'; 15-1=65535 2 else s_tf0 <= '0'; end if; end if; end if; end if; Mode 1, 16-bit Timer (contd.) Reload low 8 bit Reload high 8 bit if wt_i = "10" and wt_en_i = '1' then if wt_i = "00" and wt_en_i = '1' then s_counth0 <= unsigned(reload_i); Higher bits s_countl0 <= unsigned(reload_i); Clock/16 else counts when else if s_tmr_ctr0_en = '1' then low bits if s_tmr_ctr0_en = '1' thenTimer mode or Counter mode? if s_count_enable = '1' then count to 255 if s_count_enable = '1' then if s_c_t0 = '0' then if s_c_t0 = '0' then if s_count0 = conv_unsigned(65535,16) then if s_count0 = conv_unsigned(65535,16) then s_counth0 <= conv_unsigned(0,8); else s_countl0 <= conv_unsigned(0,8); else s_countl0 <= s_countl0+ conv_unsigned(1,1); end if; else if s_ext_edge0 = '1' then if s_count0 = conv_unsigned(65535,16) then s_countl0 <= conv_unsigned(0,8); else s_countl0 <= s_countl0+conv_unsigned(1,1); end if; end if; end if; end if; end if; end if; if s_countl0 = conv_unsigned(255,8) then s_counth0 <= s_counth0 + conv_unsigned(1,1); end if; end if; else if s_ext_edge0 = '1' then if s_count0 = conv_unsigned(65535,16) then s_counth0 <= conv_unsigned(0,8); else if s_countl0 = conv_unsigned(255,8) then s_counth0 <= s_counth0 + conv_unsigned(1,1); end if; end if; end if; end if; end if; end if; end if; Mode 2, 8-bit, auto-reload if wt_i = "00" and wt_en_i = '1' then s_countl0 <= unsigned(reload_i); Reload low 8-bit else Clock/16 count with high 8-bit Timer mode or Counter mode? if s_tmr_ctr0_en = '1' then if s_count_enable = '1' then if s_tmr_ctr0_en = '1' then if s_c_t0 = '0' then if s_countl0 = conv_unsigned(255,8) then if s_count_enable = '1' then s_countl0 <= s_counth0; if s_c_t0 = '0' or (s_ext_edge0 = '1' and s_c_t0 = '1') then else if s_count0(7 downto 0) = conv_unsigned(255,16) then s_countl0 <= s_countl0 + conv_unsigned(1,1); end if; s_tf0 <= '1'; else else if s_ext_edge0 = '1' then s_tf0 <= '0'; if s_countl0 = conv_unsigned(255,8) then s_countl0 <= s_counth0; end if; else end if; s_countl0 <= s_countl0 + conv_unsigned(1,1); end if; end if; end if; end if; end if; end if; User write high 8-bit end if; of the counter end if; if wt_i = "10" and wt_en_i = '1' then s_counth0 <= unsigned(reload_i); end if; Clock/16 Mode 3, 2 8-bit timer/counter Clock/16 if s_tmr_ctr0_en = '1' then if s_count_enable = '1' then if s_c_t0 = '0' or (s_ext_edge0 = '1' and s_c_t0 = '1') then if s_count0(7 downto 0) = conv_unsigned(255,16) then s_tf0 <= '1'; else s_tf0 <= '0'; end if; end if; end if; end if; Mode 3, 2 8-bit timer/Counter Reload low 8 bit if wt_i = "00" and wt_en_i = '1' then s_countl0 <= unsigned(reload_i); else Note that the high 8-bit counter is controlled by if s_tmr_ctr0_en = '1' then Timer 1 register bit if s_count_enable = '1' then instead of timer 0 if s_c_t0 = '0' then if s_countl0 = conv_unsigned(255,8) then s_countl0 <= conv_unsigned(0,8); else s_countl0 <= s_countl0 + conv_unsigned(1,1); end if; else if s_ext_edge0 = '1' then if s_countl0 = conv_unsigned(255,8) then s_countl0 <= conv_unsigned(0,8); else s_countl0 <= s_countl0 + conv_unsigned(1,1); end if; end if; end if; end if; end if; end if; if tcon_tr1_i = '1' then if s_count_enable = '1' then if s_count0(15 downto 8) = conv_unsigned(255,8) then s_tf1 <= '1'; else s_tf1 <= '0'; end if; end if; end if; Reload high 8 bit if wt_i = "10" and wt_en_i = '1' then s_counth0 <= unsigned(reload_i); else if tcon_tr1_i = '1' then if s_count_enable = '1' then if s_counth0 = conv_unsigned(255,8) then s_counth0 <= conv_unsigned(0,8); else s_counth0 <= s_counth0 + conv_unsigned(1,1); end if; end if; end if; end if; Mc8051_control Control_fsm & Control_mem Control_fsm Main state machine Set command signals for Control_mem Control_mem Fulfill command from command signals of Control_fsm Control_fsm & Control_mem (Block Diagram) Control_FSM EXEC2 Control_MEM FETCH EXEC1 … … … Internal register & memory operation command EXEC2 EXEC1 EXEC1 Internal Registers Internal Memory Control_fsm architecture rtl of control_fsm is ... Begin ... Find category s_instr_category <= - - Analysis instruction IC_ACALL when s_command(4 downto 0) = ACALL else of the IC_ADD_A_RR when s_command(7 downto 3) = ADD_A_RR else instruction ... p_state: process (...) begin ... If Interrupt if (...) then -- startup NULL; else if (...) then -- Execute interrupt operation ... Process Process … Interrupt Instruction Else ... -- Execute normal instruction … end if; end if; end process p_state; end rtl; Find Catalog of The Instruction s_instr_category <= IC_ACALL when s_command(4 downto 0) = ACALL IC_ADD_A_RR when s_command(7 downto 3) = ADD_A_RR IC_ADD_A_D when s_command = ADD_A_D IC_ADD_A_ATRI when s_command(7 downto 1)= ADD_A_ATRI IC_XRL_D_DATA when s_command = XRL_D_DATA … … … IC_NOP; else else else else else Interrupt Operation Increase SP Save PC(7~0) Reset interrupt flag Save PC(15~8) & Reload PC with interrupt vector if state=FETCH then ... s_nextstate <= EXEC1; elsif state=EXEC1 then ... s_nextstate <= EXEC2; elsif state=EXEC2 then ... s_nextstate <= EXEC3; elsif state=EXEC3 then ... s_nextstate <= FETCH; else s_nextstate <= FETCH; end if; Execute Instruction FETCH EXEC1 EXEC2 -- update state machine if rising_edge(clk) then state <= s_nextstate; … case s_instr_category is when IC_ACALL => if state=FETCH then ... s_nextstate <= EXEC1; elsif state=EXEC1 then ... s_nextstate <= FETCH; end if; when IC_ADD_A_RR => if state=FETCH then ... s_nextstate <= EXEC1; elsif state=EXEC1 then ... s_nextstate <= FETCH; end if; when ... ... when others => nextstate <= FETCH; end case; -- ACALL addr11 -- ADD A,Rr Execute Instruction (IC_ACCAL) Operation command to control_mem module when IC_ACALL => if state=FETCH then s_adr_mux <= "1111"; s_data_mux <= "1110"; s_regs_wr_en <= "101"; s_help16_en <= "10"; s_pc_inc_en <= "0001"; s_nextstate <= EXEC1; elsif state=EXEC1 then s_adr_mux <= "1111"; s_data_mux <= "1101"; s_regs_wr_en <= "101"; s_pc_inc_en <= "0100"; s_nextstate <= FETCH; end if; -- ACALL addr11 -- adress = sp + 1 -- data = (pc+2)(7 downto 0) -- write one byte and increment SP -- s_help16 = pc+2 -- increment program-counter -- adress = sp + 1 -- data = s_help16(15 downto 8) -- write one byte and increment SP -- load PC with 11 bits (2k block) Control_mem Internal RAM Address Internal Memory OperationCommand Internal RAM Data Internal Register Internal Registers Internal RAM