1 / 68

 未经作者允许,请勿发布该文档! yingqichen@sjtu

 未经作者允许,请勿发布该文档! yingqichen@sjtu.edu.cn. VHDL. Simulation & Synthesis. CPU.vhd (Simple Behavior Model).

angus
Download Presentation

 未经作者允许,请勿发布该文档! yingqichen@sjtu

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1.  未经作者允许,请勿发布该文档!yingqichen@sjtu.edu.cn 未经作者允许,请勿发布该文档!yingqichen@sjtu.edu.cn

  2. VHDL Simulation & Synthesis

  3. 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 ISBEGINclock_gen : PROCESS BEGIN ... END PROCESS; main_sequence : PROCESS BEGIN IF reset = '1' THEN --initialisation ... ELSE --fetchinstruction ... --incrementprogramcounter ... --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; this Model Cannot Be Synthesis

  4. CPU.vhd (Diagram) memrd memwr CPU Program counter reset pc Register of ALU pc address acca accb data acca accb Store Instruction inst_reg inst_reg Store Operator mar mar

  5. CPU • Clock Generate • Reset • Instruction Processing • Fetch Instruction From Memory • Analysis & Execute Instruction • Simple Arithmetic Operation • Data Transfer Operation • Jump Instruction

  6. 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 ISBEGINclock_gen : PROCESS BEGIN ... END PROCESS; main_sequence : PROCESS BEGIN IF reset = '1' THEN --initialisation ... ELSE --fetchinstruction ... --incrementprogramcounter ... --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 Structure • Clock Generate • Reset • Instruction Processing • Fetch Instruction From Memory • Incensement Program Counter • Analysis & Execute Instruction • Simple Arithmetic Operation • Data Transfer Operation • Jump Instruction

  7. Clock Generator clock_gen : PROCESS BEGIN clock <= '1','0' AFTER cycle_time/2; WAIT FOR cycle_time; ENDPROCESS; cycle_time/2 cycle_time/2

  8. Reset IF reset = '1' THENmemrd <= '1';memwr <= '1';pc := (OTHERS => '0');address <= (OTHERS => 'Z');data <= (OTHERS => 'Z'); WAIT UNTIL rising_edge(clock);ELSE …

  9. Fetch Instruction & increase PC clock --fetch phase address <= To_StdlogicVector(pc); WAIT FOR cycle_time/4; memrd <= '0'; WAIT FOR cycle_time/2; memrd <= '1'; --read instruction inst_reg := To_bitvector(data(7 DOWNTO 4)); --load page address 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); address data memrd Read inst_reg, mar(11~8), increase pc at this monent Page address (will be used in load/store instruction)

  10. 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 …

  11. ELSE WAIT FOR cycle_time/8; IF inst_reg = sta THEN --ouput data data <= To_StdlogicVector(acca); ELSE --ouput data data <= To_StdlogicVector(accb); END IF; WAIT FOR cycle_time/8; memwr <= '0'; WAIT FOR cycle_time/2; memwr <= '1'; WAIT FOR cycle_time/8; data <= (OTHERS => 'Z'); --wait until end of cycle WAIT UNTIL rising_edge(clock); END IF; WHEN jmp => … Execute Instruction (Load & Store Instruction) WHEN lda|ldb|sta|stb => address <= To_StdlogicVector(pc); WAIT FOR cycle_time/4; memrd <= '0'; WAIT FOR cycle_time/2; memrd <= '1'; --read page offset address mar(7 DOWNTO 0) := To_bitvector(data); --increment program counter pc := inc_bv(pc); --wait until end of cycle WAIT UNTIL rising_edge(clock); --output address of operand address <= To_StdlogicVector(mar); IF ((inst_reg = lda) OR (inst_reg = ldb)) THEN WAIT FOR cycle_time/4; memrd <= '0'; WAIT FOR cycle_time/2; 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); Get address offset(page address mar(8~11) is got in the fetching instruction step)

  12. Execute Instruction (Load & Store Instruction Waveform) clock Addressdatamemrd clock Addressdatamemrd accabcca accabcca pc mar mar pc Load Store

  13. 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; memrd <= '0'; WAIT FOR cycle_time/2; memrd <= '1'; pc(7 DOWNTO 0) := To_bitvector(data); --wait until end of cycle WAIT UNTIL rising_edge(clock); END CASE; END IF; Update high 4 bits using mar (value in mar is the jump page address) Update low 8 bits using the value on the data bus

  14. 8051 • Design File Origination • Top File • Test Platform • 8051 Modules

  15. Key Feature • Fully synchronous design • Instruction set compatible to the industry standard8051microcontroller • Optimized architecture enables fast onetofourclocksperOPcode • Up to 10timesfaster due to completely newarchitecture • User selectablenumberoftimers/counters as well as serialinterface units • Active timer/counter and serial interface units selectable via additional special • function register • Optional implementation of the multiplycommand (MUL) using a parallel multiplierunit • Optional implementation of the dividecommand (DIV) using a paralleldivider unit • Optional implementation of the decimal adjustment command (DA) • NomultiplexedI/O ports • 256 bytes internal RAM, up to 64 Kbytes ROM and up to 64 Kbytes RAM • Source code available freeofcharge under the GNU LGPL license • Technologyindependent, clearstructured, wellcommentedVHDLsourcecode • Easily expandable by adapting/changing VHDL source code • Parameterizeable via VHDL constants

  16. 8051 Diagram

  17. Ports Definitions

  18. Directory • Docu document • Mism 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 Project file for Synpilfy • Tb Test bench files • Vhdl vhdl design files

  19. 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

  20. Design Hierarchy

  21. 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;

  22. mc8051_top_struc.vhd (Block Diagram) i_mc8051_alu i_mc8051_core i_mc8051_tmrcnt i_mc8051_siu

  23. mc8051_control_struc.vhd i_control_mem i_control_fsm

  24. 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;

  25. clk reset Ram Block Diagram ram_adr_i  integer  ram_adr_i ram_data_o … ram_data_i ram_wr_i ram_en_i

  26. 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;

  27. 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;

  28. 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;

  29. 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;

  30. 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;

  31. clk reset Ram Block Diagram rom_adr_i  integer  rom_adr_i rom_data_o … rom_en_i

  32. 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) thenv_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;

  33. Testbench -- system clock definition p_clock : process variable v_loop1 : integer; begin clk <= '0'; wait for one_period/2; while true loop clk <= not clk; wait for one_period/2; end loop; end process p_clock; -------------------------------------- end sim; architecture sim of tb_mc8051_top is function FUNC_PULLUP (signal s_bidir_line : in std_logic) return std_logic is …end FUNC_PULLUP; begin i_mc8051_top : mc8051_top portmap (…); gen_portmodel : for i in 0 to 7 generate … endgenerate; p_run : process begin … reset <= '1'; wait for one_period + one_period/2 + 5 ns; reset <= '0'; wait for one_period * 5000; wait for one_period / 2; assert false report "END OF SIMULATION" severity failure; endprocess p_run;

  34. Test Bench ROM CPU RAM Reset Clock

  35. Configurable Mudules mc8051_p.vhd ------------------------------------------------------------------------------- Select how many timer/counter units should be implemented-- Default: 1constant 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!)---constant C_IMPL_N_EXT : integer := C_IMPL_N_TMR;-----------------------------------------------------------------------------

  36. Configurable Modules (contd.) entity control_mem is port { … all_tcon_tr0_o : out std_logic_vector(C_IMPL_N_TMR-1 downto 0); };…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; Use constant instead of Generic

  37. 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);

  38. Select Timer / Counter Using TSEL to select which module to use

  39. mc8051_alu_struc.vhd ADDSUB_CORE ALUMUX ALUCORE DCML_ADJUST COMB_DIVIDER COMB_MUTPLR

  40. ADDSUB_CORE one carry, one auxiliary-carry Half carry bit, so the 8-bit adder will e implemented by 2 4-bit adder

  41. Addsub_cy & addsub_ovcy

  42. 0/1 Module addsub_cy cy_i opa_i opb_i architecture rtl of addsub_cy isbegin 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; v_result := conv_unsigned(v_a,DWIDTH+2) + v_b; -- add operation else v_a(0) := '0'; v_b(0) := cy_i; 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_o rslt_o So that the “+” function will get a sum 1 bit longer Append an extra bit to handle carry

  43. Module sddsub_ovcy else v_a(0) := '0'; v_b(0) := cy_i; v_result := conv_unsigned(v_a,DWIDTH+1) - unsigned(v_b); v_la(0) := '0'; v_lb(0) := v_result(DWIDTH); v_lresult := conv_unsigned(v_la,3) - unsigned(v_lb); end if; cy_o <= v_lresult(2); ov_o <= (v_result(DWIDTH) and not(v_lresult(2))) or (v_lresult(2) and not(v_result(DWIDTH))); rslt_o(DWIDTH-2 downto 0) <= v_result(DWIDTH-1 downto 1); rslt_o(DWIDTH-1) <= v_lresult(1); end process p_addsub_ov; end generate gen_greater_one; end rtl; The add operation is separate into 2, add of bit2~0 and add of bit 3. The separation of add operation help find overflow architecture rtl of addsub_ovcy is begin gen_greater_one: if (DWIDTH > 1) generate p_addsub_ov: process (opa_i, opb_i, addsub_i, cy_i) variable v_a : unsigned(DWIDTH-1 downto 0); variable v_b : unsigned(DWIDTH-1 downto 0); variable v_result : std_logic_vector(DWIDTH downto 0); variable v_la : unsigned(1 downto 0); variable v_lb : unsigned(1 downto 0); variable v_lresult : std_logic_vector(2 downto 0); begin -- process p_addsub v_a(DWIDTH-1 downto 1) := unsigned(opa_i(DWIDTH-2 downto 0)); v_b(DWIDTH-1 downto 1) := unsigned(opb_i(DWIDTH-2 downto 0)); v_la(1) := opa_i(DWIDTH-1); v_lb(1) := opb_i(DWIDTH-1); if addsub_i = '1' then v_a(0) := '1'; 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); opa_i(2:0) opb_i (2:0) 0/1cy_i opa_i(3) opb_i (3) Carry out from bit 7 Carry out from bit 6

  44. ALU Module 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;

  45. ALUMUX ALUMUX Module Connect wires according to different input instruction addsub_core alucore dcml_adjust comb_divider comb_mltplr

  46. 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"; ...Beginprocess (…) 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; … end process;end rtl; ALUMUX Module (VHDL)

  47. 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 Mc8051_tmrctr_rtl.vhd Code structure

  48. Timer / Counter (clock) Clk16 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; end if; end process p_divide_clk; Conv_unsigned(value, bit_length)

  49. 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' thens_t0ff0 <= t0_i; s_t0ff1 <= s_t0ff0; s_t0ff2 <= s_t0ff1; end if; end if; end if; end if; end process p_sample_t0; s_ext_edge0 t0_i s_t0ff0 s_t0ff1 s_t0ff2 D Q CLK D Q CLK D Q CLK

  50. Timer / Counter (VHDL Structure) Mode 0 case s_mode0 is when "00" => ...; when "01" => ...; when "10" => ...; when "11" => ...; when others => null; end case; Mode 1 Mode 2 Mode 3

More Related