ch10_2

advertisement
未经作者允许,请勿发布该文
档!
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;
Clk16
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
Download