-- <File header>
|
-- <File header>
|
-- Project
|
-- Project
|
-- pAVR (pipelined AVR) is an 8 bit RISC controller, compatible with Atmel's
|
-- pAVR (pipelined AVR) is an 8 bit RISC controller, compatible with Atmel's
|
-- AVR core, but about 3x faster in terms of both clock frequency and MIPS.
|
-- AVR core, but about 3x faster in terms of both clock frequency and MIPS.
|
-- The increase in speed comes from a relatively deep pipeline. The original
|
-- The increase in speed comes from a relatively deep pipeline. The original
|
-- AVR core has only two pipeline stages (fetch and execute), while pAVR has
|
-- AVR core has only two pipeline stages (fetch and execute), while pAVR has
|
-- 6 pipeline stages:
|
-- 6 pipeline stages:
|
-- 1. PM (read Program Memory)
|
-- 1. PM (read Program Memory)
|
-- 2. INSTR (load Instruction)
|
-- 2. INSTR (load Instruction)
|
-- 3. RFRD (decode Instruction and read Register File)
|
-- 3. RFRD (decode Instruction and read Register File)
|
-- 4. OPS (load Operands)
|
-- 4. OPS (load Operands)
|
-- 5. ALU (execute ALU opcode or access Unified Memory)
|
-- 5. ALU (execute ALU opcode or access Unified Memory)
|
-- 6. RFWR (write Register File)
|
-- 6. RFWR (write Register File)
|
-- Version
|
-- Version
|
-- 0.32
|
-- 0.32
|
-- Date
|
-- Date
|
-- 2002 August 07
|
-- 2002 August 07
|
-- Author
|
-- Author
|
-- Doru Cuturela, doruu@yahoo.com
|
-- Doru Cuturela, doruu@yahoo.com
|
-- License
|
-- License
|
-- This program is free software; you can redistribute it and/or modify
|
-- This program is free software; you can redistribute it and/or modify
|
-- it under the terms of the GNU General Public License as published by
|
-- it under the terms of the GNU General Public License as published by
|
-- the Free Software Foundation; either version 2 of the License, or
|
-- the Free Software Foundation; either version 2 of the License, or
|
-- (at your option) any later version.
|
-- (at your option) any later version.
|
-- This program is distributed in the hope that it will be useful,
|
-- This program is distributed in the hope that it will be useful,
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
-- GNU General Public License for more details.
|
-- GNU General Public License for more details.
|
-- You should have received a copy of the GNU General Public License
|
-- You should have received a copy of the GNU General Public License
|
-- along with this program; if not, write to the Free Software
|
-- along with this program; if not, write to the Free Software
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
-- </File header>
|
-- </File header>
|
|
|
|
|
|
|
-- <File info>
|
-- <File info>
|
-- This defines pAVR's Register File.
|
-- This defines pAVR's Register File.
|
-- The Register File has 3 ports: 2 for reading and 1 for writing. All these
|
-- The Register File has 3 ports: 2 for reading and 1 for writing. All these
|
-- access all 32 locations in the register file. Apart from these 3 ports,
|
-- access all 32 locations in the register file. Apart from these 3 ports,
|
-- there are 3 special ports that access 16 bit pointer registers X, Y, Z, for
|
-- there are 3 special ports that access 16 bit pointer registers X, Y, Z, for
|
-- both reading and writing. The pointer registers are mapped on the register
|
-- both reading and writing. The pointer registers are mapped on the register
|
-- file, at addresses 26-27 (pointer register X), 28-29 (Y) and 30-31 (Z).
|
-- file, at addresses 26-27 (pointer register X), 28-29 (Y) and 30-31 (Z).
|
-- Physically, the register file consists of a memory-like entity with 26 8 bit
|
-- Physically, the register file consists of a memory-like entity with 26 8 bit
|
-- locations, and 3 16 bit registers. Together, these form the 32 locations
|
-- locations, and 3 16 bit registers. Together, these form the 32 locations
|
-- of the register file. The physical separation of locations <26 and >=26 is
|
-- of the register file. The physical separation of locations <26 and >=26 is
|
-- is invisible from outside.
|
-- is invisible from outside.
|
-- Writing on the write port and on every pointer register port can be done
|
-- Writing on the write port and on every pointer register port can be done
|
-- in parallel. However, if writing at the same time a location via the write
|
-- in parallel. However, if writing at the same time a location via the write
|
-- port and one of the pointer registers, writing via pointer register port
|
-- port and one of the pointer registers, writing via pointer register port
|
-- has priority.
|
-- has priority.
|
-- </File info>
|
-- </File info>
|
|
|
|
|
|
|
-- <File body>
|
-- <File body>
|
library work;
|
library work;
|
use work.std_util.all;
|
use work.std_util.all;
|
use work.pavr_util.all;
|
use work.pavr_util.all;
|
use work.pavr_constants.all;
|
use work.pavr_constants.all;
|
library IEEE;
|
library IEEE;
|
use IEEE.std_logic_1164.all;
|
use IEEE.std_logic_1164.all;
|
|
|
|
|
|
|
entity pavr_rf is
|
entity pavr_rf is
|
port(
|
port(
|
pavr_rf_clk: in std_logic;
|
pavr_rf_clk: in std_logic;
|
pavr_rf_res: in std_logic;
|
pavr_rf_res: in std_logic;
|
pavr_rf_syncres: in std_logic;
|
pavr_rf_syncres: in std_logic;
|
|
|
-- Read port 1
|
-- Read port 1
|
pavr_rf_rd1_addr: in std_logic_vector(4 downto 0);
|
pavr_rf_rd1_addr: in std_logic_vector(4 downto 0);
|
pavr_rf_rd1_rd: in std_logic;
|
pavr_rf_rd1_rd: in std_logic;
|
pavr_rf_rd1_do: out std_logic_vector(7 downto 0);
|
pavr_rf_rd1_do: out std_logic_vector(7 downto 0);
|
|
|
-- Read port 2
|
-- Read port 2
|
pavr_rf_rd2_addr: in std_logic_vector(4 downto 0);
|
pavr_rf_rd2_addr: in std_logic_vector(4 downto 0);
|
pavr_rf_rd2_rd: in std_logic;
|
pavr_rf_rd2_rd: in std_logic;
|
pavr_rf_rd2_do: out std_logic_vector(7 downto 0);
|
pavr_rf_rd2_do: out std_logic_vector(7 downto 0);
|
|
|
-- Write port
|
-- Write port
|
pavr_rf_wr_addr: in std_logic_vector(4 downto 0);
|
pavr_rf_wr_addr: in std_logic_vector(4 downto 0);
|
pavr_rf_wr_wr: in std_logic;
|
pavr_rf_wr_wr: in std_logic;
|
pavr_rf_wr_di: in std_logic_vector(7 downto 0);
|
pavr_rf_wr_di: in std_logic_vector(7 downto 0);
|
|
|
-- Pointer registers
|
-- Pointer registers
|
pavr_rf_x: out std_logic_vector(15 downto 0);
|
pavr_rf_x: out std_logic_vector(15 downto 0);
|
pavr_rf_x_wr: in std_logic;
|
pavr_rf_x_wr: in std_logic;
|
pavr_rf_x_di: in std_logic_vector(15 downto 0);
|
pavr_rf_x_di: in std_logic_vector(15 downto 0);
|
|
|
pavr_rf_y: out std_logic_vector(15 downto 0);
|
pavr_rf_y: out std_logic_vector(15 downto 0);
|
pavr_rf_y_wr: in std_logic;
|
pavr_rf_y_wr: in std_logic;
|
pavr_rf_y_di: in std_logic_vector(15 downto 0);
|
pavr_rf_y_di: in std_logic_vector(15 downto 0);
|
|
|
pavr_rf_z: out std_logic_vector(15 downto 0);
|
pavr_rf_z: out std_logic_vector(15 downto 0);
|
pavr_rf_z_wr: in std_logic;
|
pavr_rf_z_wr: in std_logic;
|
pavr_rf_z_di: in std_logic_vector(15 downto 0)
|
pavr_rf_z_di: in std_logic_vector(15 downto 0)
|
);
|
);
|
end;
|
end;
|
|
|
|
|
|
|
architecture pavr_rf_arch of pavr_rf is
|
architecture pavr_rf_arch of pavr_rf is
|
|
|
signal pavr_rf_x_int: std_logic_vector(15 downto 0);
|
signal pavr_rf_x_int: std_logic_vector(15 downto 0);
|
signal pavr_rf_y_int: std_logic_vector(15 downto 0);
|
signal pavr_rf_y_int: std_logic_vector(15 downto 0);
|
signal pavr_rf_z_int: std_logic_vector(15 downto 0);
|
signal pavr_rf_z_int: std_logic_vector(15 downto 0);
|
|
|
type t_pavr_rf_data_array is array (0 to 25) of std_logic_vector(7 downto 0);
|
type t_pavr_rf_data_array is array (0 to 25) of std_logic_vector(7 downto 0);
|
signal pavr_rf_data_array: t_pavr_rf_data_array;
|
signal pavr_rf_data_array: t_pavr_rf_data_array;
|
|
|
begin
|
begin
|
|
|
-- Read port 1
|
-- Read port 1
|
process
|
process
|
variable is_x, is_y, is_z: std_logic;
|
variable is_x, is_y, is_z: std_logic;
|
variable tv: std_logic_vector(2 downto 0);
|
variable tv: std_logic_vector(2 downto 0);
|
begin
|
begin
|
tv := int_to_std_logic_vector(0, 3);
|
tv := int_to_std_logic_vector(0, 3);
|
|
|
wait until ((pavr_rf_clk'event) and (pavr_rf_clk = '1'));
|
wait until ((pavr_rf_clk'event) and (pavr_rf_clk = '1'));
|
|
|
if (pavr_rf_rd1_addr(4 downto 1) = "1101") then
|
if (pavr_rf_rd1_addr(4 downto 1) = "1101") then
|
is_x := '1';
|
is_x := '1';
|
else
|
else
|
is_x := '0';
|
is_x := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_rd1_addr(4 downto 1) = "1110") then
|
if (pavr_rf_rd1_addr(4 downto 1) = "1110") then
|
is_y := '1';
|
is_y := '1';
|
else
|
else
|
is_y := '0';
|
is_y := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_rd1_addr(4 downto 1) = "1111") then
|
if (pavr_rf_rd1_addr(4 downto 1) = "1111") then
|
is_z := '1';
|
is_z := '1';
|
else
|
else
|
is_z := '0';
|
is_z := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_rd1_rd = '1') then
|
if (pavr_rf_rd1_rd = '1') then
|
tv := is_x & is_y & is_z;
|
tv := is_x & is_y & is_z;
|
case tv is
|
case tv is
|
when "000" =>
|
when "000" =>
|
pavr_rf_rd1_do <= pavr_rf_data_array(std_logic_vector_to_nat(pavr_rf_rd1_addr));
|
pavr_rf_rd1_do <= pavr_rf_data_array(std_logic_vector_to_nat(pavr_rf_rd1_addr));
|
when "100" =>
|
when "100" =>
|
if (pavr_rf_rd1_addr(0) = '0') then
|
if (pavr_rf_rd1_addr(0) = '0') then
|
pavr_rf_rd1_do <= pavr_rf_x_int(7 downto 0);
|
pavr_rf_rd1_do <= pavr_rf_x_int(7 downto 0);
|
else
|
else
|
pavr_rf_rd1_do <= pavr_rf_x_int(15 downto 8);
|
pavr_rf_rd1_do <= pavr_rf_x_int(15 downto 8);
|
end if;
|
end if;
|
when "010" =>
|
when "010" =>
|
if (pavr_rf_rd1_addr(0) = '0') then
|
if (pavr_rf_rd1_addr(0) = '0') then
|
pavr_rf_rd1_do <= pavr_rf_y_int(7 downto 0);
|
pavr_rf_rd1_do <= pavr_rf_y_int(7 downto 0);
|
else
|
else
|
pavr_rf_rd1_do <= pavr_rf_y_int(15 downto 8);
|
pavr_rf_rd1_do <= pavr_rf_y_int(15 downto 8);
|
end if;
|
end if;
|
when others =>
|
when others =>
|
if (pavr_rf_rd1_addr(0) = '0') then
|
if (pavr_rf_rd1_addr(0) = '0') then
|
pavr_rf_rd1_do <= pavr_rf_z_int(7 downto 0);
|
pavr_rf_rd1_do <= pavr_rf_z_int(7 downto 0);
|
else
|
else
|
pavr_rf_rd1_do <= pavr_rf_z_int(15 downto 8);
|
pavr_rf_rd1_do <= pavr_rf_z_int(15 downto 8);
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
|
|
|
-- Read port 2
|
-- Read port 2
|
process
|
process
|
variable is_x, is_y, is_z: std_logic;
|
variable is_x, is_y, is_z: std_logic;
|
variable tv: std_logic_vector(2 downto 0);
|
variable tv: std_logic_vector(2 downto 0);
|
begin
|
begin
|
tv := int_to_std_logic_vector(0, 3);
|
tv := int_to_std_logic_vector(0, 3);
|
|
|
wait until ((pavr_rf_clk'event) and (pavr_rf_clk = '1'));
|
wait until ((pavr_rf_clk'event) and (pavr_rf_clk = '1'));
|
|
|
if (pavr_rf_rd2_addr(4 downto 1) = "1101") then
|
if (pavr_rf_rd2_addr(4 downto 1) = "1101") then
|
is_x := '1';
|
is_x := '1';
|
else
|
else
|
is_x := '0';
|
is_x := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_rd2_addr(4 downto 1) = "1110") then
|
if (pavr_rf_rd2_addr(4 downto 1) = "1110") then
|
is_y := '1';
|
is_y := '1';
|
else
|
else
|
is_y := '0';
|
is_y := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_rd2_addr(4 downto 1) = "1111") then
|
if (pavr_rf_rd2_addr(4 downto 1) = "1111") then
|
is_z := '1';
|
is_z := '1';
|
else
|
else
|
is_z := '0';
|
is_z := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_rd2_rd = '1') then
|
if (pavr_rf_rd2_rd = '1') then
|
tv := is_x & is_y & is_z;
|
tv := is_x & is_y & is_z;
|
case tv is
|
case tv is
|
when "000" =>
|
when "000" =>
|
pavr_rf_rd2_do <= pavr_rf_data_array(std_logic_vector_to_nat(pavr_rf_rd2_addr));
|
pavr_rf_rd2_do <= pavr_rf_data_array(std_logic_vector_to_nat(pavr_rf_rd2_addr));
|
when "100" =>
|
when "100" =>
|
if (pavr_rf_rd2_addr(0) = '0') then
|
if (pavr_rf_rd2_addr(0) = '0') then
|
pavr_rf_rd2_do <= pavr_rf_x_int(7 downto 0);
|
pavr_rf_rd2_do <= pavr_rf_x_int(7 downto 0);
|
else
|
else
|
pavr_rf_rd2_do <= pavr_rf_x_int(15 downto 8);
|
pavr_rf_rd2_do <= pavr_rf_x_int(15 downto 8);
|
end if;
|
end if;
|
when "010" =>
|
when "010" =>
|
if (pavr_rf_rd2_addr(0) = '0') then
|
if (pavr_rf_rd2_addr(0) = '0') then
|
pavr_rf_rd2_do <= pavr_rf_y_int(7 downto 0);
|
pavr_rf_rd2_do <= pavr_rf_y_int(7 downto 0);
|
else
|
else
|
pavr_rf_rd2_do <= pavr_rf_y_int(15 downto 8);
|
pavr_rf_rd2_do <= pavr_rf_y_int(15 downto 8);
|
end if;
|
end if;
|
when others =>
|
when others =>
|
if (pavr_rf_rd2_addr(0) = '0') then
|
if (pavr_rf_rd2_addr(0) = '0') then
|
pavr_rf_rd2_do <= pavr_rf_z_int(7 downto 0);
|
pavr_rf_rd2_do <= pavr_rf_z_int(7 downto 0);
|
else
|
else
|
pavr_rf_rd2_do <= pavr_rf_z_int(15 downto 8);
|
pavr_rf_rd2_do <= pavr_rf_z_int(15 downto 8);
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
|
|
|
-- Write port and pointer registers
|
-- Write port and pointer registers
|
process(pavr_rf_clk, pavr_rf_res, pavr_rf_syncres,
|
process(pavr_rf_clk, pavr_rf_res, pavr_rf_syncres,
|
pavr_rf_wr_addr, pavr_rf_wr_wr, pavr_rf_wr_di, pavr_rf_x_wr, pavr_rf_y_wr, pavr_rf_z_wr,
|
pavr_rf_wr_addr, pavr_rf_wr_wr, pavr_rf_wr_di, pavr_rf_x_wr, pavr_rf_y_wr, pavr_rf_z_wr,
|
pavr_rf_x_di, pavr_rf_y_di, pavr_rf_z_di)
|
pavr_rf_x_di, pavr_rf_y_di, pavr_rf_z_di)
|
variable is_x, is_y, is_z: std_logic;
|
variable is_x, is_y, is_z: std_logic;
|
variable tv: std_logic_vector(2 downto 0);
|
variable tv: std_logic_vector(2 downto 0);
|
begin
|
begin
|
tv := int_to_std_logic_vector(0, 3);
|
tv := int_to_std_logic_vector(0, 3);
|
|
|
if (pavr_rf_wr_addr(4 downto 1) = "1101") then
|
if (pavr_rf_wr_addr(4 downto 1) = "1101") then
|
is_x := '1';
|
is_x := '1';
|
else
|
else
|
is_x := '0';
|
is_x := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_wr_addr(4 downto 1) = "1110") then
|
if (pavr_rf_wr_addr(4 downto 1) = "1110") then
|
is_y := '1';
|
is_y := '1';
|
else
|
else
|
is_y := '0';
|
is_y := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_wr_addr(4 downto 1) = "1111") then
|
if (pavr_rf_wr_addr(4 downto 1) = "1111") then
|
is_z := '1';
|
is_z := '1';
|
else
|
else
|
is_z := '0';
|
is_z := '0';
|
end if;
|
end if;
|
|
|
if (pavr_rf_res = '1') then
|
if (pavr_rf_res = '1') then
|
-- Asynchronous reset
|
-- Asynchronous reset
|
pavr_rf_x_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_x_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_y_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_y_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_z_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_z_int <= int_to_std_logic_vector(0, 16);
|
elsif ((pavr_rf_clk'event) and (pavr_rf_clk = '1')) then
|
elsif ((pavr_rf_clk'event) and (pavr_rf_clk = '1')) then
|
|
|
-- Write port
|
-- Write port
|
if (pavr_rf_wr_wr = '1') then
|
if (pavr_rf_wr_wr = '1') then
|
tv := is_x & is_y & is_z;
|
tv := is_x & is_y & is_z;
|
case tv is
|
case tv is
|
when "000" =>
|
when "000" =>
|
pavr_rf_data_array(std_logic_vector_to_nat(pavr_rf_wr_addr)) <= pavr_rf_wr_di;
|
pavr_rf_data_array(std_logic_vector_to_nat(pavr_rf_wr_addr)) <= pavr_rf_wr_di;
|
when "100" =>
|
when "100" =>
|
if (pavr_rf_wr_addr(0) = '0') then
|
if (pavr_rf_wr_addr(0) = '0') then
|
pavr_rf_x_int(7 downto 0) <= pavr_rf_wr_di;
|
pavr_rf_x_int(7 downto 0) <= pavr_rf_wr_di;
|
else
|
else
|
pavr_rf_x_int(15 downto 8) <= pavr_rf_wr_di;
|
pavr_rf_x_int(15 downto 8) <= pavr_rf_wr_di;
|
end if;
|
end if;
|
when "010" =>
|
when "010" =>
|
if (pavr_rf_wr_addr(0) = '0') then
|
if (pavr_rf_wr_addr(0) = '0') then
|
pavr_rf_y_int(7 downto 0) <= pavr_rf_wr_di;
|
pavr_rf_y_int(7 downto 0) <= pavr_rf_wr_di;
|
else
|
else
|
pavr_rf_y_int(15 downto 8) <= pavr_rf_wr_di;
|
pavr_rf_y_int(15 downto 8) <= pavr_rf_wr_di;
|
end if;
|
end if;
|
when others =>
|
when others =>
|
if (pavr_rf_wr_addr(0) = '0') then
|
if (pavr_rf_wr_addr(0) = '0') then
|
pavr_rf_z_int(7 downto 0) <= pavr_rf_wr_di;
|
pavr_rf_z_int(7 downto 0) <= pavr_rf_wr_di;
|
else
|
else
|
pavr_rf_z_int(15 downto 8) <= pavr_rf_wr_di;
|
pavr_rf_z_int(15 downto 8) <= pavr_rf_wr_di;
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- Write pointer registers. Possibly overwrite the above write.
|
-- Write pointer registers. Possibly overwrite the above write.
|
if (pavr_rf_x_wr = '1') then
|
if (pavr_rf_x_wr = '1') then
|
pavr_rf_x_int <= pavr_rf_x_di;
|
pavr_rf_x_int <= pavr_rf_x_di;
|
end if;
|
end if;
|
if (pavr_rf_y_wr = '1') then
|
if (pavr_rf_y_wr = '1') then
|
pavr_rf_y_int <= pavr_rf_y_di;
|
pavr_rf_y_int <= pavr_rf_y_di;
|
end if;
|
end if;
|
if (pavr_rf_z_wr = '1') then
|
if (pavr_rf_z_wr = '1') then
|
pavr_rf_z_int <= pavr_rf_z_di;
|
pavr_rf_z_int <= pavr_rf_z_di;
|
end if;
|
end if;
|
|
|
if (pavr_rf_syncres = '1') then
|
if (pavr_rf_syncres = '1') then
|
-- Synchronous reset
|
-- Synchronous reset
|
pavr_rf_x_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_x_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_y_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_y_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_z_int <= int_to_std_logic_vector(0, 16);
|
pavr_rf_z_int <= int_to_std_logic_vector(0, 16);
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
|
|
|
-- Zero-level assignments
|
-- Zero-level assignments
|
pavr_rf_x <= pavr_rf_x_int;
|
pavr_rf_x <= pavr_rf_x_int;
|
pavr_rf_y <= pavr_rf_y_int;
|
pavr_rf_y <= pavr_rf_y_int;
|
pavr_rf_z <= pavr_rf_z_int;
|
pavr_rf_z <= pavr_rf_z_int;
|
|
|
end;
|
end;
|
-- </File body>
|
-- </File body>
|
|
|