RISCV V1
This commit is contained in:
parent
683ac9a8d4
commit
9505af3467
26
Makefile
26
Makefile
|
@ -0,0 +1,26 @@
|
|||
PARTS = alu ram
|
||||
CP = ghdl
|
||||
FLAGS = --std=08
|
||||
ALUSRC = src/alu.vhd tb/tb_alu.vhd
|
||||
RAMSRC = src/ram_block.vhd src/ram.vhd tb/rb_ram.vhd
|
||||
STOP = 6000ns
|
||||
|
||||
all: $(PARTS)
|
||||
|
||||
alu: $(ALUSRC)
|
||||
$(CP) -a $(FLAGS) $(ALUSRC)
|
||||
$(CP) -e $(FLAGS) tb_$@
|
||||
$(CP) -r $(FLAGS) tb_$@ --wave=$@.ghw --stop-time=$(STOP)
|
||||
|
||||
ram: $(RAMSRC)
|
||||
$(CP) -a $(FLAGS) $(RAMSRC)
|
||||
$(CP) -e $(FLAGS) tb_$@
|
||||
$(CP) -r $(FLAGS) tb_$@ --wave=$@.ghw --stop-time=$(STOP)
|
||||
|
||||
clean:
|
||||
find . -name '*.o' -exec rm -r {} \;
|
||||
find . -name '*.cf' -exec rm -r {} \;
|
||||
find . -name '*.ghw' -exec rm -r {} \;
|
||||
find . -name '*_tb' -exec rm -r {} \;
|
||||
|
||||
.PHONY: all alu clean
|
|
@ -0,0 +1,42 @@
|
|||
-- Decoder.vhd
|
||||
-- Date: Tue Jan 30 17:10:48 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: schnick@nickr.eu
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
-- Entity decode: Decoder currently supporting read operations
|
||||
entity Decoder is
|
||||
port(
|
||||
Instruction : in std_logic_vector(15 downto 0); -- Instruction from instruction memory
|
||||
AluOpcd : out std_logic_vector(3 downto 0); -- alu opcode
|
||||
RegOp1 : out std_logic_vector(3 downto 0); -- Rj: first register to read
|
||||
RegOp2 : out std_logic_vector(3 downto 0); -- Rk: second register to read
|
||||
RegWrite : out std_logic_vector(3 downto 0) -- Ri: the register to write to
|
||||
);
|
||||
end Decoder;
|
||||
|
||||
architecture Implementation of Decoder is
|
||||
|
||||
begin
|
||||
|
||||
Decode : process(Instruction(11 downto 8), Instruction(15 downto 12),
|
||||
Instruction(3 downto 0), Instruction(7 downto 4))
|
||||
begin
|
||||
|
||||
-- assign the alway same positions
|
||||
RegOp1 <= Instruction(11 downto 8);
|
||||
RegOp2 <= Instruction(7 downto 4);
|
||||
RegWrite <= Instruction(15 downto 12);
|
||||
|
||||
-- Alu opcodes
|
||||
case Instruction(3 downto 0) is
|
||||
when "0000" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" | "1000" | "1010" => AluOpcd <= Instruction(3 downto 0); -- R-Types
|
||||
when "0001" | "1001" => AluOpcd <= Instruction(7 downto 4); -- S-Types
|
||||
when "1110" => AluOpcd <= Instruction(7 downto 4); -- B-Types (to be debated)
|
||||
when others => AluOpcd <= "1111"; -- if unsure, do nothing
|
||||
end case;
|
||||
end process Decode;
|
||||
|
||||
end Implementation;
|
|
@ -0,0 +1,19 @@
|
|||
-- Immediate.vhd
|
||||
-- Date: Tue Jan 30 20:04:49 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: schnick@nickr.eu
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
entity Immediate is
|
||||
port (
|
||||
ImmIn : in std_logic_vector(15 downto 0);
|
||||
ImmOut : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end Immediate;
|
||||
|
||||
architecture Implementation of Immediate is
|
||||
|
||||
begin
|
||||
ImmOut <= ImmIn;
|
||||
end Implementation;
|
|
@ -0,0 +1,40 @@
|
|||
-- ProgramCounter.vhd
|
||||
-- Date: Tue Jan 30 20:54:56 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: schnick@nickr.eu
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity ProgramCounter is
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
PcEnable : in std_logic;
|
||||
AddrCalc : in std_logic_vector(15 downto 0);
|
||||
Jump : in std_logic;
|
||||
Addr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end ProgramCounter;
|
||||
|
||||
architecture Implementation of ProgramCounter is
|
||||
signal Address : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal AddressPlus : std_logic_vector(15 downto 0) := (others => '0');
|
||||
begin
|
||||
|
||||
UpdatePc : process(Clk)
|
||||
begin
|
||||
if rising_edge(Clk) then
|
||||
if PcEnable = '1' then
|
||||
if Jump = '1' then
|
||||
Address <= AddrCalc;
|
||||
else
|
||||
Address <= AddressPlus;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process UpdatePc;
|
||||
|
||||
AddressPlus <= (std_logic_vector(to_unsigned(to_integer(unsigned(Address)) + 1, 16)));
|
||||
Addr <= Address;
|
||||
|
||||
end Implementation;
|
|
@ -0,0 +1,33 @@
|
|||
-- ProgramMemory.vhd
|
||||
-- Date: Tue Jan 30 17:01:12 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: schnick@nickr.eu
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity ProgramMemory is
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
InstrAddr : in std_logic_vector(15 downto 0);
|
||||
Instruction : out std_logic_vector(15 downto 0);
|
||||
Immediate : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end ProgramMemory;
|
||||
|
||||
architecture Implementation of ProgramMemory is
|
||||
type MemoryType is array(0 to 65536) of std_logic_vector(15 downto 0);
|
||||
signal Memory : MemoryType := (others => (others => '0'));
|
||||
begin
|
||||
|
||||
SynchronRead : process(Clk)
|
||||
begin
|
||||
|
||||
if rising_edge(Clk) then
|
||||
Instruction <= Memory(to_integer(unsigned(InstrAddr)));
|
||||
Immediate <= Memory(to_integer(unsigned(InstrAddr) + 1));
|
||||
end if;
|
||||
|
||||
end process SynchronRead;
|
||||
|
||||
end Implementation;
|
|
@ -0,0 +1,53 @@
|
|||
-- alu.vhd
|
||||
-- Date: Tue Jan 30 10:02:24 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: yannick.reiss@protonmail.ch
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity Alu is
|
||||
port (
|
||||
alu_op : in std_logic_vector(3 downto 0);
|
||||
input1 : in std_logic_vector(15 downto 0);
|
||||
input2 : in std_logic_vector(15 downto 0);
|
||||
result : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end Alu;
|
||||
|
||||
architecture Implementation of Alu is
|
||||
|
||||
begin
|
||||
Alu_logic : process(alu_op, input1, input2)
|
||||
begin
|
||||
case alu_op is
|
||||
when "0000" => result <= std_logic_vector(unsigned(input1) + unsigned(input2));
|
||||
-- ADD
|
||||
when "0010" => result <= std_logic_vector(signed(input1) - signed(input2));
|
||||
-- SUB
|
||||
when "0011" => result <= std_logic_vector(unsigned(input1) sll to_integer(unsigned(input2)));
|
||||
-- SLL
|
||||
when "0100" =>
|
||||
if (signed(input1) < signed(input2)) then
|
||||
result <= std_logic_vector(to_unsigned(1, 16));
|
||||
else
|
||||
result <= std_logic_vector(to_unsigned(0, 16));
|
||||
end if; -- SLT
|
||||
when "0101" =>
|
||||
if (unsigned(input1) < unsigned(input2)) then
|
||||
result <= std_logic_vector(to_unsigned(1, 16));
|
||||
else
|
||||
result <= std_logic_vector(to_unsigned(0, 16));
|
||||
end if; -- SLTU
|
||||
when "0110" => result <= input1 xor input2; -- XOR
|
||||
when "0111" => result <= std_logic_vector(unsigned(input1) srl to_integer(unsigned(input2)));
|
||||
-- SRL
|
||||
when "1000" => result <= std_logic_vector(signed(input1) sra to_integer(unsigned(input2)));
|
||||
-- SRA
|
||||
when "1010" => result <= input1 or input2; -- OR
|
||||
when "1011" => result <= input1 and input2; -- AND
|
||||
when others => result <= std_logic_vector(to_unsigned(0, 16));
|
||||
end case;
|
||||
end process Alu_logic;
|
||||
|
||||
end Implementation;
|
|
@ -0,0 +1,134 @@
|
|||
-- cpu16.vhd
|
||||
-- Date: Tue Jan 30 15:19:09 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: schnick@nickr.eu
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
entity Cpu16 is
|
||||
port (
|
||||
Clk : in std_logic;
|
||||
Switches : in std_logic_vector(15 downto 0);
|
||||
SDA : inout std_logic;
|
||||
SDL : inout std_logic;
|
||||
LED : out std_logic_vector(15 downto 0);
|
||||
RGB : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end Cpu16;
|
||||
|
||||
architecture Implementation of Cpu16 is
|
||||
|
||||
signal RamAddrA : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RamAddrB : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RamWriteEnable : std_logic := '0';
|
||||
signal RamDataWrite : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RamReadA : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RamReadB : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal AluOpcode : std_logic_vector(3 downto 0) := "1111"; -- Some nop operation
|
||||
signal AluIn1 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal AluIn2 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal AluResult : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RegisterWriteEnable : std_logic := '0';
|
||||
signal RegisterRegister1 : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal RegisterRegister2 : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal RegisterRegisterW : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal RegisterDataIn : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RegisterDataOut1 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RegisterDataOut2 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal InstructionCounter : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RawInstruction : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal DecoderRegOp1 : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal DecoderRegOp2 : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal DecoderRegWrite : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal NextInstruction : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal ImmediateValue : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal PcEnable : std_logic := '0';
|
||||
signal Jump : std_logic := '0';
|
||||
begin
|
||||
|
||||
-- Include Entities
|
||||
Ramblock : entity work.Ram(Behavioral)
|
||||
port map(
|
||||
Clk => Clk,
|
||||
AddrA => RamAddrA,
|
||||
AddrB => RamAddrB,
|
||||
WriteEnable => RamWriteEnable,
|
||||
DataIn => RamDataWrite,
|
||||
ReadA => RamReadA,
|
||||
ReadB => RamReadB,
|
||||
DirectIn => Switches,
|
||||
DirectOut => LED
|
||||
);
|
||||
|
||||
Alu : entity work.Alu(Implementation)
|
||||
port map(
|
||||
alu_op => AluOpcode,
|
||||
input1 => AluIn1,
|
||||
input2 => AluIn2,
|
||||
result => AluResult
|
||||
);
|
||||
|
||||
Regs : entity work.Registerset(Implementation)
|
||||
port map(
|
||||
Clk => Clk,
|
||||
WriteEnable => RegisterWriteEnable,
|
||||
Register1 => RegisterRegister1,
|
||||
Register2 => RegisterRegister2,
|
||||
RegisterW => RegisterRegisterW,
|
||||
DataIn => RegisterDataIn,
|
||||
DataOut1 => RegisterDataOut1,
|
||||
DataOut2 => RegisterDataOut2
|
||||
);
|
||||
|
||||
Instructions : entity work.ProgramMemory(Implementation)
|
||||
port map(
|
||||
Clk => Clk,
|
||||
InstrAddr => InstructionCounter,
|
||||
Instruction => RawInstruction,
|
||||
Immediate => NextInstruction
|
||||
);
|
||||
|
||||
Decoder : entity work.Decoder(Implementation)
|
||||
port map(
|
||||
Instruction => RawInstruction,
|
||||
AluOpcd => AluOpcode,
|
||||
RegOp1 => RegisterRegister1,
|
||||
RegOp2 => RegisterRegister2,
|
||||
RegWrite => RegisterRegisterW
|
||||
);
|
||||
|
||||
ImmUseless : entity work.Immediate(Implementation)
|
||||
port map(
|
||||
ImmIn => NextInstruction,
|
||||
ImmOut => ImmediateValue
|
||||
);
|
||||
|
||||
PC : entity work.ProgramCounter(Implementation)
|
||||
port map(
|
||||
Clk => Clk,
|
||||
PcEnable => PcEnable,
|
||||
AddrCalc => AluResult,
|
||||
Jump => Jump,
|
||||
Addr => InstructionCounter
|
||||
);
|
||||
|
||||
AluSetInput : process(ImmediateValue, InstructionCounter, RegisterDataOut1,
|
||||
RegisterDataOut2)
|
||||
begin
|
||||
|
||||
case RawInstruction(3 downto 0) is
|
||||
when "0000" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" | "1000" | "1010" | "1110" => AluIn1 <= RegisterDataOut1;
|
||||
AluIn2 <= RegisterDataOut2;
|
||||
when "0001" | "1001" => AluIn1 <= RegisterDataOut1;
|
||||
AluIn2 <= ImmediateValue;
|
||||
when others => AluIn1 <= InstructionCounter;
|
||||
AluIn2 <= RegisterDataOut2;
|
||||
|
||||
|
||||
end case;
|
||||
end process AluSetInput;
|
||||
|
||||
|
||||
RGB <= Switches(7 downto 0);
|
||||
|
||||
end Implementation;
|
|
@ -0,0 +1,107 @@
|
|||
-- ram.vhd
|
||||
-- Date: Tue Jan 30 12:26:41 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: yannick.reiss@protonmail.ch
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity Ram is
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
AddrA : in std_logic_vector(15 downto 0);
|
||||
AddrB : in std_logic_vector(15 downto 0);
|
||||
WriteEnable : in std_logic;
|
||||
DataIn : in std_logic_vector(15 downto 0);
|
||||
ReadA : out std_logic_vector(15 downto 0);
|
||||
ReadB : out std_logic_vector(15 downto 0);
|
||||
DirectIn : in std_logic_vector(15 downto 0);
|
||||
DirectOut : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end Ram;
|
||||
|
||||
architecture Behavioral of Ram is
|
||||
|
||||
signal we1 : std_logic := '0';
|
||||
signal we2 : std_logic := '0';
|
||||
|
||||
signal SReadA1 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal SReadB1 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
|
||||
signal SReadA2 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal SReadB2 : std_logic_vector(15 downto 0) := (others => '0');
|
||||
|
||||
signal Mode1 : std_logic := '1';
|
||||
signal Mode2 : std_logic := '0';
|
||||
signal ZeroWord : std_logic_vector(15 downto 0) := (others => '0');
|
||||
|
||||
signal BoardInput : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal BoardOutput : std_logic_vector(15 downto 0) := (others => '0');
|
||||
begin
|
||||
|
||||
block1 : entity work.Ram_Block(Memory)
|
||||
port map(
|
||||
Clk => Clk,
|
||||
WriteEnable => we1,
|
||||
AddrA => AddrA(14 downto 0),
|
||||
AddrB => AddrB(14 downto 0),
|
||||
Input => DataIn,
|
||||
ReadA => SReadA1,
|
||||
ReadB => SReadB1
|
||||
);
|
||||
|
||||
block2 : entity work.Ram_Block(Memory)
|
||||
port map(
|
||||
Clk => Clk,
|
||||
WriteEnable => we2,
|
||||
AddrA => AddrA(14 downto 0),
|
||||
AddrB => AddrB(14 downto 0),
|
||||
Input => DataIn,
|
||||
ReadA => SReadA2,
|
||||
ReadB => SReadB2
|
||||
);
|
||||
|
||||
-- Set write enable
|
||||
we1 <= WriteEnable and not AddrA(15);
|
||||
we2 <= WriteEnable and AddrA(15);
|
||||
|
||||
DirectIO : process(clk)
|
||||
begin
|
||||
|
||||
if rising_edge(clk) then
|
||||
-- must be treated as register
|
||||
BoardInput <= DirectIn;
|
||||
|
||||
-- handle Directin
|
||||
if unsigned(AddrA) = 1 then
|
||||
ReadA <= BoardInput;
|
||||
else
|
||||
case AddrA(15) is
|
||||
when '1' =>
|
||||
ReadA <= SReadA2;
|
||||
when others => ReadA <= SReadA1;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
if unsigned(AddrB) = 1 then
|
||||
ReadB <= BoardInput;
|
||||
else
|
||||
case AddrB(15) is
|
||||
when '1' =>
|
||||
ReadB <= SReadB2;
|
||||
|
||||
when others => ReadB <= SReadB1;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- handle Directout
|
||||
if unsigned(AddrB) = 2 and WriteEnable = '1' then
|
||||
BoardOutput <= DataIn;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process DirectIO;
|
||||
|
||||
DirectOut <= BoardOutput;
|
||||
|
||||
end Behavioral;
|
|
@ -0,0 +1,48 @@
|
|||
-- ram_block.vhd
|
||||
-- Date: Tue Jan 30 11:18:02 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: yannick.reiss@protonmail.ch
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity Ram_Block is
|
||||
port (
|
||||
Clk : in std_logic;
|
||||
WriteEnable : in std_logic;
|
||||
AddrA : in std_logic_vector(14 downto 0);
|
||||
AddrB : in std_logic_vector(14 downto 0);
|
||||
Input : in std_logic_vector(15 downto 0);
|
||||
ReadA : out std_logic_vector(15 downto 0);
|
||||
ReadB : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end Ram_Block;
|
||||
|
||||
architecture Memory of Ram_Block is
|
||||
|
||||
type MemBlock is array(0 to 32768) of std_logic_vector(15 downto 0);
|
||||
|
||||
signal Store : MemBlock := (others => (others => '0'));
|
||||
signal RegA : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal RegB : std_logic_vector(15 downto 0) := (others => '0');
|
||||
begin
|
||||
|
||||
ReadWrite : process(Clk)
|
||||
begin
|
||||
|
||||
if rising_edge(Clk) then
|
||||
|
||||
if WriteEnable = '1' then
|
||||
Store(to_integer(unsigned(AddrB))) <= Input;
|
||||
end if;
|
||||
|
||||
RegA <= Store(to_integer(unsigned(AddrA)));
|
||||
RegB <= Store(to_integer(unsigned(AddrB)));
|
||||
|
||||
end if;
|
||||
end process ReadWrite;
|
||||
|
||||
ReadA <= RegA;
|
||||
ReadB <= RegB;
|
||||
|
||||
end Memory;
|
|
@ -0,0 +1,41 @@
|
|||
-- register.vhd
|
||||
-- Date: Tue Jan 30 14:47:16 2024
|
||||
-- Author: Yannick Reiß
|
||||
-- E-Mail: schnick@nickr.eu
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity Registerset is
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
WriteEnable : in std_logic;
|
||||
Register1 : in std_logic_vector(3 downto 0);
|
||||
Register2 : in std_logic_vector(3 downto 0);
|
||||
RegisterW : in std_logic_vector(3 downto 0);
|
||||
DataIn : in std_logic_vector(15 downto 0);
|
||||
DataOut1 : out std_logic_vector(15 downto 0);
|
||||
DataOut2 : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end Registerset;
|
||||
|
||||
architecture Implementation of Registerset is
|
||||
type RegisterBlock is array(0 to 15) of std_logic_vector(15 downto 0);
|
||||
signal Registers : RegisterBlock := (others => (others => '0'));
|
||||
|
||||
begin
|
||||
|
||||
WriteRegister : process(Clk)
|
||||
begin
|
||||
|
||||
if rising_edge(Clk) then
|
||||
if WriteEnable = '1' and unsigned(RegisterW) > 0 then
|
||||
Registers (to_integer(unsigned(RegisterW))) <= DataIn;
|
||||
end if;
|
||||
end if;
|
||||
end process WriteRegister;
|
||||
|
||||
DataOut1 <= Registers(to_integer(unsigned(Register1)));
|
||||
DataOut2 <= Registers(to_integer(unsigned(Register2)));
|
||||
|
||||
end Implementation;
|
Loading…
Reference in New Issue