-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated ISA support to RV32IMZcsr - Passes riscv-compliance. Integer divide/rem in 34 cycles. Integer multiply in 2 cycles (when using xilinx dsp blocks!) Saved multiple cycles from fetch/memory load stages by short-cutting the start of memory requests. Compliant misaligned exceptions for jumps,loads and stores. Addrs starting 0xFxxxxxxx ignore alignment requests (assumes mmio space). Added CSRs for riscv-compliance requirements. Source ran through a formatter for ease of use.
- Loading branch information
Showing
12 changed files
with
2,555 additions
and
1,445 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
---------------------------------------------------------------------------------- | ||
-- Company: | ||
-- Engineer: | ||
-- | ||
-- Create Date: 12.11.2018 22:51:11 | ||
-- Design Name: | ||
-- Module Name: rpu_core_tb - Behavioral | ||
-- Project Name: | ||
-- Target Devices: | ||
-- Tool Versions: | ||
-- Description: | ||
-- | ||
-- Dependencies: | ||
-- | ||
-- Revision: | ||
-- Revision 0.01 - File Created | ||
-- Additional Comments: | ||
-- | ||
---------------------------------------------------------------------------------- | ||
|
||
|
||
library IEEE; | ||
use IEEE.STD_LOGIC_1164.ALL; | ||
|
||
-- Uncomment the following library declaration if using | ||
-- arithmetic functions with Signed or Unsigned values | ||
use IEEE.NUMERIC_STD.ALL; | ||
|
||
-- Uncomment the following library declaration if instantiating | ||
-- any Xilinx leaf cells in this code. | ||
--library UNISIM; | ||
--use UNISIM.VComponents.all; | ||
|
||
library work; | ||
use work.constants.all; | ||
|
||
entity alu_int32_div_tb is | ||
-- Port ( ); | ||
end alu_int32_div_tb; | ||
|
||
architecture Behavioral of alu_int32_div_tb is | ||
|
||
|
||
-- The RPU core definition | ||
component alu_int32_div is | ||
Port ( | ||
I_clk : in STD_LOGIC; | ||
I_exec : in STD_LOGIC; | ||
I_dividend : in STD_LOGIC_VECTOR (XLEN32M1 downto 0); | ||
I_divisor : in STD_LOGIC_VECTOR (XLEN32M1 downto 0); | ||
I_op : in STD_LOGIC_VECTOR (1 downto 0); | ||
O_dataResult : out STD_LOGIC_VECTOR (XLEN32M1 downto 0); | ||
O_done : out STD_LOGIC; | ||
O_int : out std_logic | ||
); | ||
end component; | ||
|
||
signal I_clk : std_logic := '0'; | ||
signal I_exec : std_logic := '0'; | ||
signal I_dividend : std_logic_vector(31 downto 0) := (others => '0'); | ||
signal I_divisor : std_logic_vector(31 downto 0) := (others => '0'); | ||
signal I_op : std_logic_vector(1 downto 0) := (others => '0'); | ||
signal O_dataResult : std_logic_vector(31 downto 0) := (others => '0'); | ||
signal O_done : std_logic := '0'; | ||
signal O_int : std_logic := '0'; | ||
|
||
|
||
-- Clock period definitions | ||
constant I_clk_period : time := 10 ns; | ||
BEGIN | ||
|
||
-- Instantiate the Unit Under Test (UUT) | ||
uut: alu_int32_div PORT MAP ( | ||
I_clk => I_clk, | ||
I_exec => I_exec, | ||
I_dividend => I_dividend, | ||
I_divisor => I_divisor, | ||
I_op => I_op, | ||
O_dataResult => O_dataResult, | ||
O_done => O_done, | ||
O_int => O_int | ||
); | ||
|
||
-- Clock process definitions | ||
I_clk_process :process | ||
begin | ||
I_clk <= '0'; | ||
wait for I_clk_period/2; | ||
I_clk <= '1'; | ||
wait for I_clk_period/2; | ||
end process; | ||
|
||
|
||
-- Stimulus process | ||
stim_proc: process | ||
begin | ||
-- hold reset state for 100 ns. | ||
wait for 100 ns; | ||
|
||
wait for I_clk_period*10; | ||
-- insert stimulus here | ||
|
||
I_dividend <= X"ffffffff"; | ||
I_divisor <= X"00000000"; | ||
I_op <= ALU_INT32_DIV_OP_DIVU; | ||
I_exec <= '1'; | ||
wait for I_clk_period; | ||
I_exec <= '0'; | ||
|
||
wait for I_clk_period*500; | ||
|
||
|
||
I_dividend <= X"0000000a"; | ||
I_divisor <= X"0000000a"; | ||
I_op <= ALU_INT32_DIV_OP_REMU; | ||
I_exec <= '1'; | ||
wait for I_clk_period; | ||
I_exec <= '0'; | ||
|
||
wait for I_clk_period*500; | ||
|
||
I_dividend <= X"00001001"; | ||
I_divisor <= X"00000111"; | ||
I_op <= ALU_INT32_DIV_OP_REM; | ||
I_exec <= '1'; | ||
wait for I_clk_period; | ||
I_exec <= '0'; | ||
|
||
wait for I_clk_period*500; | ||
|
||
I_dividend <= X"ffff0001"; | ||
I_divisor <= X"00000111"; | ||
I_op <= ALU_INT32_DIV_OP_DIV; | ||
I_exec <= '1'; | ||
wait for I_clk_period; | ||
I_exec <= '0'; | ||
|
||
wait for I_clk_period*500; | ||
|
||
|
||
-- I_dividend <= X"ffff0001"; | ||
-- I_divisor <= X"00000111"; | ||
-- I_op <= ALU_INT32_DIV_OP_DIVU; | ||
-- I_exec <= '1'; | ||
-- wait for I_clk_period; | ||
-- I_exec <= '0'; | ||
-- wait for I_clk_period*500; | ||
|
||
I_dividend <= X"00011101"; | ||
I_divisor <= X"00000001"; | ||
I_op <= ALU_INT32_DIV_OP_DIV; | ||
I_exec <= '1'; | ||
wait for I_clk_period; | ||
I_exec <= '0'; | ||
|
||
wait for I_clk_period*500; | ||
|
||
I_dividend <= X"00010001"; | ||
I_divisor <= X"00000111"; | ||
I_op <= ALU_INT32_DIV_OP_DIV; | ||
I_exec <= '1'; | ||
wait for I_clk_period; | ||
I_exec <= '0'; | ||
wait; | ||
end process; | ||
|
||
|
||
end Behavioral; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
---------------------------------------------------------------------------------- | ||
-- Project Name: RISC-V CPU | ||
-- Description: ALU unit for 32-bit integer division ops | ||
-- | ||
---------------------------------------------------------------------------------- | ||
-- Copyright 2020 Colin Riley | ||
-- | ||
-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
-- you may not use this file except in compliance with the License. | ||
-- You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
---------------------------------------------------------------------------------- | ||
|
||
library IEEE; | ||
use IEEE.STD_LOGIC_1164.all; | ||
|
||
-- Uncomment the following library declaration if using | ||
-- arithmetic functions with Signed or Unsigned values | ||
use IEEE.NUMERIC_STD.all; | ||
library work; | ||
use work.constants.all; | ||
|
||
entity alu_int32_div is | ||
port ( | ||
I_clk : in STD_LOGIC; | ||
I_exec : in STD_LOGIC; | ||
I_dividend : in STD_LOGIC_VECTOR (XLEN32M1 downto 0); | ||
I_divisor : in STD_LOGIC_VECTOR (XLEN32M1 downto 0); | ||
I_op : in STD_LOGIC_VECTOR (1 downto 0); | ||
O_dataResult : out STD_LOGIC_VECTOR (XLEN32M1 downto 0); | ||
O_done : out STD_LOGIC; | ||
O_int : out std_logic | ||
); | ||
end alu_int32_div; | ||
|
||
architecture Behavioral of alu_int32_div is | ||
signal s_done : std_logic := '0'; | ||
signal s_int : std_logic := '0'; | ||
signal s_op : std_logic_vector(1 downto 0) := (others => '0'); | ||
signal s_result : std_logic_vector(XLEN32M1 downto 0) := (others => '0'); | ||
signal s_outsign : std_logic := '0'; | ||
signal s_ur : unsigned(XLEN32M1 downto 0) := (others => '0'); | ||
|
||
signal s_i : integer := 0; | ||
signal s_N : unsigned(XLEN32M1 downto 0) := (others => '0'); | ||
signal s_D : unsigned(XLEN32M1 downto 0) := (others => '0'); | ||
signal s_R : unsigned(XLEN32M1 downto 0) := (others => '0'); | ||
signal s_Q : unsigned(XLEN32M1 downto 0) := (others => '0'); | ||
constant STATE_IDLE : integer := 0; | ||
constant STATE_INFLIGHTU : integer := 1; | ||
constant STATE_COMPLETE : integer := 2; | ||
|
||
signal s_state : integer := 0; | ||
begin | ||
|
||
process (I_clk) | ||
begin | ||
if rising_edge(I_clk) then | ||
if s_state = STATE_IDLE then | ||
s_done <= '0'; | ||
if I_exec = '1' then | ||
s_op <= I_op; | ||
s_done <= '0'; | ||
|
||
if (I_divisor = X"00000000") then | ||
s_state <= STATE_COMPLETE; | ||
s_Q <= X"ffffffff"; | ||
|
||
if I_dividend(31) = '1' then | ||
s_R <= unsigned(-signed(I_dividend)); | ||
else | ||
s_R <= unsigned(I_dividend); | ||
end if; | ||
|
||
if (I_op = ALU_INT32_DIV_OP_DIV) or (I_op = ALU_INT32_DIV_OP_DIVU) then | ||
s_outsign <= '0'; | ||
else | ||
s_outsign <= I_dividend(31); | ||
end if; | ||
|
||
elsif (I_divisor = X"00000001") and (I_op = ALU_INT32_DIV_OP_DIV) then | ||
s_state <= STATE_COMPLETE; | ||
s_R <= X"00000000"; | ||
if I_dividend(31) = '1' then | ||
s_Q <= unsigned(-signed(I_dividend)); | ||
else | ||
s_Q <= unsigned(I_dividend); | ||
end if; | ||
s_outsign <= I_dividend(31); | ||
|
||
else | ||
if I_op(ALU_INT32_DIV_OP_UNSIGNED_BIT) = '1' then | ||
s_state <= STATE_INFLIGHTU; | ||
s_N <= unsigned(I_dividend); | ||
s_D <= unsigned(I_divisor); | ||
s_ur <= X"00000000"; | ||
s_Q <= X"00000000"; | ||
s_R <= X"00000000"; | ||
|
||
s_i <= 31; | ||
s_outsign <= '0'; | ||
else | ||
s_state <= STATE_INFLIGHTU; | ||
|
||
if (I_op = ALU_INT32_DIV_OP_DIV) then | ||
s_outsign <= I_dividend(31) xor I_divisor(31); | ||
else | ||
s_outsign <= I_dividend(31); | ||
end if; | ||
|
||
if I_dividend(31) = '1' then | ||
s_N <= unsigned(-signed(I_dividend)); | ||
else | ||
s_N <= unsigned(I_dividend); | ||
end if; | ||
|
||
if I_divisor(31) = '1' then | ||
s_D <= unsigned(-signed(I_divisor)); | ||
else | ||
s_D <= unsigned(I_divisor); | ||
end if; | ||
|
||
s_ur <= X"00000000"; | ||
|
||
s_Q <= X"00000000"; | ||
s_R <= X"00000000"; | ||
|
||
s_i <= 31; | ||
|
||
end if; | ||
end if; | ||
end if; | ||
|
||
|
||
elsif s_state = STATE_INFLIGHTU then | ||
-- binary integer long division loop | ||
if (s_R(30 downto 0) & s_N(s_i)) >= s_D then | ||
s_R <= (s_R(30 downto 0) & s_N(s_i)) - s_D; | ||
s_Q(s_i) <= '1'; | ||
else | ||
s_R <= s_R(30 downto 0) & s_N(s_i); | ||
end if; | ||
|
||
if s_i = 0 then | ||
s_state <= STATE_COMPLETE; | ||
else | ||
s_i <= s_i - 1; | ||
end if; | ||
|
||
|
||
elsif s_state = STATE_COMPLETE then | ||
|
||
if (s_op = ALU_INT32_DIV_OP_DIV) or (s_op = ALU_INT32_DIV_OP_DIVU) then | ||
if (s_outsign = '1') then | ||
s_result <= std_logic_vector(-signed(std_logic_vector(s_Q))); | ||
else | ||
s_result <= std_logic_vector(s_Q); | ||
end if; | ||
else | ||
if (s_outsign = '1') then | ||
s_result <= std_logic_vector(-signed(std_logic_vector(s_R))); | ||
else | ||
s_result <= std_logic_vector(s_R); | ||
end if; | ||
end if; | ||
|
||
s_done <= '1'; | ||
s_state <= STATE_IDLE; | ||
end if; | ||
end if; | ||
end process; | ||
|
||
O_dataResult <= s_result; | ||
O_done <= s_done; | ||
O_int <= s_int; | ||
end Behavioral; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.