Sei sulla pagina 1di 68

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)
CPU





memrd
memwr
reset
address
data
pc
acca accb
inst_reg
mar
pc
acca accb
inst_reg
mar
Program
counter
Register
of ALU
Store
Instruction
Store
Operator
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);
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);
clock
address
memrd
data
Read inst_reg,
mar(11~8),
increase pc at this
monent
Page address (will be
used in load/store
instruction)
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)
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)
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 Waveform)
clock
Address

data

memrd

pc
mar
acca
bcca
clock
Address

data

memrd

pc
mar
acca
bcca
Load Store
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
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 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

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 integer







ram_adr_i
ram_data_o
ram_data_i
clk
reset
ram_wr_i
ram_en_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 integer







rom_adr_i
rom_data_o clk
reset
rom_en_i
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;
Testbench
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
port map ();
gen_portmodel : for i in 0 to 7 generate

end generate;
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;
end process p_run;
-- 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;
Test
Bench
CPU
ROM
RAM
Reset
Clock
Configurable Mudules
-----------------------------------------------------------------------------
-- 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!)---
constant C_IMPL_N_EXT : integer := C_IMPL_N_TMR;
-----------------------------------------------------------------------------

mc8051_p.vhd
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
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
Half carry bit, so the 8-bit
adder will e implemented
by 2 4-bit adder
one carry, one
auxiliary-carry
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;
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;
So that the + function
will get a sum 1 bit longer
opa_i
opb_i
cy_i
0/1
cy_o
rslt_o
Append an extra
bit to handle carry
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;
Module sddsub_ovcy
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)
opa_i(3)
opb_i (3)
0/1
cy_i
Carry out
from bit 7
Carry out
from bit 6
The add operation is separate
into 2, add of bit2~0 and add
of bit 3. The separation of
add operation help find
overflow
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;
ALUMUX
Module
ALUMUX









addsub_core
alucore
dcml_adjust
comb_divider
comb_mltplr
Connect
wires
according to
different
input
instruction
ALUMUX
Module
(VHDL)
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;


end process;
end rtl;
Timer /
Counter
Mc8051_tmrctr_rtl.vhd

Code structure
Clk/16
Falling Edge Detection
& Synchronize
Timer/Counter 0
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
Falling Edge Detection
& Synchronize
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;
end if;
end process p_divide_clk;

Clk16
Conv_unsigned(value, bit_length)
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;
end if;
end if;
end if;
end if;
end process p_sample_t0;
D Q

CLK
D Q

CLK
D Q

CLK
t0_i s_t0ff0 s_t0ff1 s_t0ff2
s_ext_edge0
Timer / Counter (VHDL
Structure)
case s_mode0 is

when "00" =>
...;

when "01" =>
...;

when "10" =>
...;

when "11" =>
...;

when others => null;

end case;

Mode 0
Mode 1
Mode 2
Mode 3
Timer / Counter (TCON)
Timer / Counter (TMOD)
Mode 0, 13-bit Timer
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';
else
s_tf0 <= '0';
end if;
end if;
end if;
end if;
8191 = 2
13
- 1
Clock/16
Mode 0, 13-bit Timer (contd.)
if wt_i = "00" and wt_en_i = '1' then
s_countl0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_count0 = conv_unsigned(8191,16) 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_count0 = conv_unsigned(8191,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 wt_i = "10" and wt_en_i = '1' then
s_counth0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_count0 = conv_unsigned(8191,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;
else
if s_ext_edge0 = '1' then
if s_count0 = conv_unsigned(8191,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;
Clock/16
Timer mode or Counter mode?
Higher bits
counts when
low bits
count to 255
Reload low 8 bit Reload low bits
Mode 1, 16-bit Timer
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';
else
s_tf0 <= '0';
end if;
end if;
end if;
end if;
2
15
-1=65535
Clock/16
Mode 1, 16-bit Timer (contd.)
if wt_i = "00" and wt_en_i = '1' then
s_countl0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' 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;
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 wt_i = "10" and wt_en_i = '1' then
s_counth0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' 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;
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;
Higher bits
counts when
low bits
count to 255
Clock/16
Timer mode or Counter mode?
Reload high 8 bit Reload low 8 bit
Mode 2, 8-bit, auto-reload
if wt_i = "00" and wt_en_i = '1' then
s_countl0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_countl0 = conv_unsigned(255,8) then
s_countl0 <= s_counth0;
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 <= s_counth0;
else
s_countl0 <= s_countl0 + conv_unsigned(1,1);
end if;
end if;
end if;
end if;
end if;
end if;
if wt_i = "10" and wt_en_i = '1' then
s_counth0 <= unsigned(reload_i);
end if;
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;
Clock/16
Timer mode or Counter mode?
Reload low 8-bit
count with high 8-bit
User write high 8-bit
of the counter
Clock/16
Mode 3, 2 8-bit timer/counter
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;
Clock/16
Mode 3, 2 8-bit timer/Counter
if wt_i = "00" and wt_en_i = '1' then
s_countl0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
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;

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;
Reload low 8 bit
Note that the high 8-bit
counter is controlled by
Timer 1 register bit
instead of timer 0
Reload high 8 bit
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)
FETCH
EXEC1
EXEC2
EXEC1
EXEC2
EXEC1



Control_FSM
I nternal
register &
memory
operation
command
Control_MEM
Internal
Memory
Internal
Registers
Control_fsm
architecture rtl of control_fsm is
...
Begin
...
s_instr_category <= - - Analysis instruction
IC_ACALL when s_command(4 downto 0) = ACALL else
IC_ADD_A_RR when s_command(7 downto 3) = ADD_A_RR else
...
p_state: process (...)
begin
...
if (...) then -- startup
NULL;
else
if (...) then -- Execute interrupt operation
...

Else
... -- Execute normal instruction

end if;
end if;
end process p_state;
end rtl;
Find category
of the
instruction
Process
Interrupt
If Interrupt
Process
Instruction
Find Catalog of The
Instruction
s_instr_category <=
IC_ACALL when s_command(4 downto 0) = ACALL else
IC_ADD_A_RR when s_command(7 downto 3) = ADD_A_RR else
IC_ADD_A_D when s_command = ADD_A_D else
IC_ADD_A_ATRI when s_command(7 downto 1)= ADD_A_ATRI else
IC_XRL_D_DATA when s_command = XRL_D_DATA else



IC_NOP;
Interrupt Operation
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;
Increase SP
Reset
interrupt
flag
Save
PC(7~0)
Save
PC(15~8) &
Reload PC
with interrupt
vector
Execute Instruction
case s_instr_category is
when IC_ACALL => -- ACALL addr11
if state=FETCH then
...
s_nextstate <= EXEC1;
elsif state=EXEC1 then
...
s_nextstate <= FETCH;
end if;
when IC_ADD_A_RR => -- 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;
FETCH
EXEC1
EXEC2
-- update state machine
if rising_edge(clk) then
state <= s_nextstate;

Execute Instruction
(IC_ACCAL)
when IC_ACALL => -- ACALL addr11
if state=FETCH then
s_adr_mux <= "1111"; -- adress = sp + 1
s_data_mux <= "1110"; -- data = (pc+2)(7 downto 0)
s_regs_wr_en <= "101"; -- write one byte and increment SP
s_help16_en <= "10"; -- s_help16 = pc+2
s_pc_inc_en <= "0001"; -- increment program-counter
s_nextstate <= EXEC1;
elsif state=EXEC1 then
s_adr_mux <= "1111"; -- adress = sp + 1
s_data_mux <= "1101"; -- data = s_help16(15 downto 8)
s_regs_wr_en <= "101"; -- write one byte and increment SP
s_pc_inc_en <= "0100"; -- load PC with 11 bits (2k block)
s_nextstate <= FETCH;
end if;
Operation
command to
control_mem
module
Control_mem
Internal RAM Address

Internal RAM Data


Internal Register
Internal Memory
OperationCommand
Internal
Registers
Internal
RAM

Potrebbero piacerti anche