Initial revision

Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@939 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2013-02-07 14:50:03 +00:00
parent 0d10a1c1c6
commit 026c442fce
8 changed files with 778 additions and 0 deletions
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
## NOTE: Do not edit this file.
##
vlib work
vcom -explicit -93 "../src/core/ram_2c_2r_2w.vhd"
vcom -explicit -93 "../src/core/j1.vhd"
vcom -explicit -93 "../src/tb_j1.vhd"
vmap work
vsim -t 1ps -lib work tb_j1
do {tb_j1.wave.do}
view wave
view structure
view signals
run 1us
+58
View File
@@ -0,0 +1,58 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /tb_j1/sys_clk_i
add wave -noupdate -format Logic /tb_j1/sys_rst_i
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/io_din
add wave -noupdate -format Logic /tb_j1/io_rd
add wave -noupdate -format Logic /tb_j1/io_wr
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/io_addr
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/io_dout
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/inst_addr
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/inst_din
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/data_addr
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/data_din
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/data_dout
add wave -noupdate -format Logic /tb_j1/data_we
add wave -noupdate -format Logic /tb_j1/data_en
add wave -noupdate -divider {J1 internals}
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/insn
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/immediate
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/ramrd
add wave -noupdate -format Literal /tb_j1/uut/dsp
add wave -noupdate -format Literal /tb_j1/uut/dsp2
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/st0
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/st02
add wave -noupdate -format Logic /tb_j1/uut/dstkw2
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/pc
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/pc2
add wave -noupdate -format Literal /tb_j1/uut/rsp
add wave -noupdate -format Literal /tb_j1/uut/rsp2
add wave -noupdate -format Logic /tb_j1/uut/rstkw2
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/rstkd2
add wave -noupdate -format Logic /tb_j1/uut/ramwe2
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/pc_plus_1
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/dstack
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/rstack
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/st1
add wave -noupdate -format Literal -radix hexadecimal /tb_j1/uut/rst0
add wave -noupdate -format Literal /tb_j1/uut/st0sel
add wave -noupdate -format Logic /tb_j1/uut/is_alu
add wave -noupdate -format Logic /tb_j1/uut/is_lit
add wave -noupdate -format Literal /tb_j1/uut/dd
add wave -noupdate -format Literal /tb_j1/uut/rd
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {1600185 ps} 0}
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
update
WaveRestoreZoom {0 ps} {1050 ns}
+187
View File
@@ -0,0 +1,187 @@
module j1(
input sys_clk_i, input sys_rst_i, input [15:0] io_din,
output io_rd, output io_wr, output [15:0] io_addr, output [15:0] io_dout);
wire [15:0] insn;
wire [15:0] immediate = { 1'b0, insn[14:0] };
wire [15:0] ramrd;
reg [4:0] dsp; // Data stack pointer
reg [4:0] _dsp;
reg [15:0] st0; // Return stack pointer
reg [15:0] _st0;
wire _dstkW; // D stack write
reg [12:0] pc;
reg [12:0] _pc;
reg [4:0] rsp;
reg [4:0] _rsp;
reg _rstkW; // R stack write
reg [15:0] _rstkD;
wire _ramWE; // RAM write enable
wire [15:0] pc_plus_1;
assign pc_plus_1 = pc + 1;
// The D and R stacks
reg [15:0] dstack[0:31];
reg [15:0] rstack[0:31];
always @(posedge sys_clk_i)
begin
if (_dstkW)
dstack[_dsp] = st0;
if (_rstkW)
rstack[_rsp] = _rstkD;
end
wire [15:0] st1 = dstack[dsp];
wire [15:0] rst0 = rstack[rsp];
// st0sel is the ALU operation. For branch and call the operation
// is T, for 0branch it is N. For ALU ops it is loaded from the instruction
// field.
reg [3:0] st0sel;
always @*
begin
case (insn[14:13])
2'b00: st0sel = 0; // ubranch
2'b10: st0sel = 0; // call
2'b01: st0sel = 1; // 0branch
2'b11: st0sel = insn[11:8]; // ALU
default: st0sel = 4'bxxxx;
endcase
end
`define RAMS 3
genvar i;
`define w (16 >> `RAMS)
`define w1 (`w - 1)
generate
for (i = 0; i < (1 << `RAMS); i=i+1) begin : ram
// RAMB16_S18_S18
RAMB16_S2_S2
ram(
.DIA(0),
// .DIPA(0),
.DOA(insn[`w*i+`w1:`w*i]),
.WEA(0),
.ENA(1),
.CLKA(sys_clk_i),
.ADDRA({_pc}),
.DIB(st1[`w*i+`w1:`w*i]),
// .DIPB(2'b0),
.WEB(_ramWE & (_st0[15:14] == 0)),
.ENB(|_st0[15:14] == 0),
.CLKB(sys_clk_i),
.ADDRB(_st0[15:1]),
.DOB(ramrd[`w*i+`w1:`w*i]));
end
endgenerate
// Compute the new value of T.
always @*
begin
if (insn[15])
_st0 = immediate;
else
case (st0sel)
4'b0000: _st0 = st0;
4'b0001: _st0 = st1;
4'b0010: _st0 = st0 + st1;
4'b0011: _st0 = st0 & st1;
4'b0100: _st0 = st0 | st1;
4'b0101: _st0 = st0 ^ st1;
4'b0110: _st0 = ~st0;
4'b0111: _st0 = {16{(st1 == st0)}};
4'b1000: _st0 = {16{($signed(st1) < $signed(st0))}};
4'b1001: _st0 = st1 >> st0[3:0];
4'b1010: _st0 = st0 - 1;
4'b1011: _st0 = rst0;
4'b1100: _st0 = |st0[15:14] ? io_din : ramrd;
4'b1101: _st0 = st1 << st0[3:0];
4'b1110: _st0 = {rsp, 3'b000, dsp};
4'b1111: _st0 = {16{(st1 < st0)}};
default: _st0 = 16'hxxxx;
endcase
end
wire is_alu = (insn[15:13] == 3'b011);
wire is_lit = (insn[15]);
assign io_rd = (is_alu & (insn[11:8] == 4'hc));
assign io_wr = _ramWE;
assign io_addr = st0;
assign io_dout = st1;
assign _ramWE = is_alu & insn[5];
assign _dstkW = is_lit | (is_alu & insn[7]);
wire [1:0] dd = insn[1:0]; // D stack delta
wire [1:0] rd = insn[3:2]; // R stack delta
always @*
begin
if (is_lit) begin // literal
_dsp = dsp + 1;
_rsp = rsp;
_rstkW = 0;
_rstkD = _pc;
end else if (is_alu) begin
_dsp = dsp + {dd[1], dd[1], dd[1], dd};
_rsp = rsp + {rd[1], rd[1], rd[1], rd};
_rstkW = insn[6];
_rstkD = st0;
end else begin // jump/call
// predicated jump is like DROP
if (insn[15:13] == 3'b001) begin
_dsp = dsp - 1;
end else begin
_dsp = dsp;
end
if (insn[15:13] == 3'b010) begin // call
_rsp = rsp + 1;
_rstkW = 1;
_rstkD = {pc_plus_1[14:0], 1'b0};
end else begin
_rsp = rsp;
_rstkW = 0;
_rstkD = _pc;
end
end
end
always @*
begin
if (sys_rst_i)
_pc = pc;
else
if ((insn[15:13] == 3'b000) |
((insn[15:13] == 3'b001) & (|st0 == 0)) |
(insn[15:13] == 3'b010))
_pc = insn[12:0];
else if (is_alu & insn[12])
_pc = rst0[15:1];
else
_pc = pc_plus_1;
end
always @(posedge sys_clk_i)
begin
if (sys_rst_i) begin
pc <= 0;
dsp <= 0;
st0 <= 0;
rsp <= 0;
end else begin
dsp <= _dsp;
pc <= _pc;
st0 <= _st0;
rsp <= _rsp;
end
end
endmodule // j1
+282
View File
@@ -0,0 +1,282 @@
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
entity j1 is
Generic
(
R_STACK_SIZE : natural := 32;
D_STACK_SIZE : natural := 32
);
Port
(
sys_clk_i : in std_logic;
sys_rst_i : in std_logic;
io_din : in unsigned(15 downto 0);
io_rd : out std_logic;
io_wr : out std_logic;
io_addr : out unsigned(15 downto 0);
io_dout : out unsigned(15 downto 0);
inst_din : in unsigned(15 downto 0);
inst_addr : out unsigned(12 downto 0);
data_addr : out unsigned(12 downto 0);
data_we : out std_logic;
data_en : out std_logic;
data_din : in unsigned(15 downto 0);
data_dout : out unsigned(15 downto 0)
);
end j1;
architecture behave of j1 is
signal insn : unsigned(15 downto 0);
signal immediate : unsigned(15 downto 0);
signal ramrd : unsigned(15 downto 0);
signal dsp : unsigned(4 downto 0); -- Data stack pointer (register)
signal dsp2 : unsigned(4 downto 0); -- register
signal st0 : unsigned(15 downto 0); -- Return stack pointer (register)
signal st02 : unsigned(15 downto 0); -- register
signal dstkW2 : std_logic; -- D stack write
signal pc : unsigned(12 downto 0); -- register
signal pc2 : unsigned(12 downto 0); -- register
signal rsp : unsigned(4 downto 0); -- register
signal rsp2 : unsigned(4 downto 0); -- register
signal rstkW2 : std_logic; -- register
signal rstkD2 : unsigned(15 downto 0); -- register
signal ramWE2 : std_logic; -- RAM write enable
signal pc_plus_1 : unsigned(15 downto 0);
type stack_t is array (integer range <>) of unsigned(15 downto 0);
signal dstack : stack_t(0 to D_STACK_SIZE-1); -- register
signal rstack : stack_t(0 to R_STACK_SIZE-1); -- register
signal st1 : unsigned(15 downto 0);
signal rst0 : unsigned(15 downto 0);
signal st0sel : unsigned(3 downto 0);
signal is_alu : BOOLEAN;
signal is_lit : BOOLEAN;
signal dd : unsigned(1 downto 0); -- D stack delta
signal rd : unsigned(1 downto 0); -- R stack delta
signal stack_ram_en : std_logic; -- helper for RAM R/W
signal stack_ram_we : std_logic; -- helper for RAM R/W
begin
-- LINE 25:
pc_plus_1 <= ("000" & pc) + 1;
-- LINE 37:
st1 <= dstack(to_integer(dsp));
rst0 <= rstack(to_integer(rsp));
immediate <= '1' & insn(14 downto 0);
-- LINE 112:
is_alu <= (insn(15 downto 13) = "011");
is_lit <= (insn(15) = '1');
-- LINE 115:
io_rd <= '1' when (is_alu and (insn(11 downto 8) = X"C")) else '0';
io_wr <= ramWE2;
io_addr <= st0;
io_dout <= st1;
ramWE2 <= '1' when (is_alu and (insn(5) = '1')) else '0';
dstkW2 <= '1' when (is_lit or (is_alu and insn(7) = '1')) else '0';
dd <= insn(1 downto 0);
rd <= insn(3 downto 2);
-- LINE 27:
-- The D and R stacks
proc_d_and_r_stack:
process(sys_clk_i)
begin
if rising_edge(sys_clk_i) then
if dstkW2 = '1' then
dstack(to_integer(dsp2)) <= st0;
end if;
if rstkW2 = '1' then
rstack(to_integer(rsp2)) <= rstkD2;
end if;
end if;
end process;
-- LINE 40:
-- st0sel is the ALU operation. For branch and call the operation
-- is T, for 0branch it is N. For ALU ops it is loaded from the instruction
-- field.
proc_aluop_sel:
process(insn)
begin
case insn(14 downto 13) is
when "00" => st0sel <= "0000";
when "10" => st0sel <= "0000";
when "01" => st0sel <= "0001";
when "11" => st0sel <= insn(11 downto 8);
when others => st0sel <= "XXXX";
end case;
end process;
-- LINE 55:
-- define RAMS outside this module
insn <= inst_din;
inst_addr <= pc2(12 downto 0);
data_en <= not (st02(15) or st02(14));
data_we <= ramWE2 and not (st02(15) or st02(14));
ramrd <= data_din;
data_dout <= st1;
data_addr <= st02(13 downto 1);
-- LINE 85:
-- Compute the new value of T.
proc_alu:
process(insn, immediate, st0sel, st0, st1, rst0, rsp, dsp)
begin
if insn(15) = '1' then
st02 <= immediate;
else
case st0sel is
when "0000" => st02 <= st0;
when "0001" => st02 <= st1;
when "0010" => st02 <= st0 + st1;
when "0011" => st02 <= st0 and st1;
when "0100" => st02 <= st0 or st1;
when "0101" => st02 <= st0 xor st1;
when "0110" => st02 <= not st0;
when "0111" =>
if st1 = st0 then
st02 <= X"FFFF";
else
st02 <= X"0000";
end if;
when "1000" =>
if signed(st1) < signed(st0) then
st02 <= X"FFFF";
else
st02 <= X"0000";
end if;
when "1001" => st02 <= st1 srl to_integer(st0(3 downto 0));
when "1010" => st02 <= st0 - 1;
when "1011" => st02 <= rst0;
when "1100" =>
if st0(15) = '1' or st0(14) = '1' then -- LINE 104: ????
st02 <= io_din;
else
st02 <= ramrd;
end if;
when "1101" => st02 <= st1 sll to_integer(st0(3 downto 0));
when "1110" => st02 <= "000" & rsp & "000" & dsp; -- LINE 106: ????
when "1111" =>
if st1 < st0 then
st02 <= X"FFFF";
else
st02 <= X"0000";
end if;
when others => st02 <= "XXXXXXXXXXXXXXXX";
end case;
end if;
end process;
-- LINE 126:
proc_stack_ctrl:
process(is_lit, is_alu, pc2, dd, rd, insn, st0, pc_plus_1, rsp, dsp)
begin
if is_lit then -- literal
dsp2 <= dsp + 1;
rsp2 <= rsp;
rstkW2 <= '0';
rstkD2 <= "000" & pc2;
elsif is_alu then
dsp2 <= dsp + (dd(1) & dd(1) & dd(1) & dd);
rsp2 <= rsp + (rd(1) & rd(1) & rd(1) & rd);
rstkW2 <= insn(6);
rstkD2 <= st0;
else -- jump/call
-- predicated jump is like DROP
if insn(15 downto 13) = "001" then
dsp2 <= dsp - 1;
else
dsp2 <= dsp; -- *default
end if;
if insn(15 downto 13) = "010" then -- call
rsp2 <= rsp + 1;
rstkW2 <= '1';
rstkD2 <= pc_plus_1(14 downto 0) & '0';
else
rsp2 <= rsp; -- *default
rstkW2 <= '0'; -- *default
rstkD2 <= "000" & pc2; -- *default
end if;
end if;
end process;
-- LINE 157:
proc_pc:
process(sys_rst_i, is_alu, insn, pc, st0, rst0, pc_plus_1)
begin
if sys_rst_i = '1' then
pc2 <= pc;
else
if ((insn(15 downto 13) = "000")
or ((insn(15 downto 13) = "001")
and (st0 = X"0000"))
or (insn(15 downto 13) = "010")) then
pc2 <= insn(12 downto 0);
elsif is_alu and (insn(12) = '1') then -- return
pc2 <= rst0(13 downto 1); -- LINE 167: ????
else
pc2 <= pc_plus_1(12 downto 0); -- LINE 169: truncation ????
end if;
end if;
end process;
-- LINE 172:
proc_next:
process(sys_clk_i)
begin
if rising_edge(sys_clk_i) then
if sys_rst_i = '1' then
pc <= (others => '0');
dsp <= (others => '0');
st0 <= (others => '0');
rsp <= (others => '0');
else
dsp <= dsp2;
pc <= pc2;
st0 <= st02;
rsp <= rsp2;
end if;
end if;
end process;
end behave;
+84
View File
@@ -0,0 +1,84 @@
--------------------------------------------------------------------------
-- Project: Generic RAM. Infers BlockRAM for Xilinx
-- This file: On-chip RAM
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- 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
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity ram_2c_2r_2w is
Generic
(
addr_width : integer := 3;
data_width : integer := 8
);
Port (
clka : in STD_LOGIC;
clkb : in STD_LOGIC;
en_a : in STD_LOGIC;
en_b : in STD_LOGIC;
we_a : in STD_LOGIC;
we_b : in STD_LOGIC;
addr_a : in unsigned (addr_width-1 downto 0);
addr_b : in unsigned (addr_width-1 downto 0);
din_a : in unsigned (data_width-1 downto 0);
din_b : in unsigned (data_width-1 downto 0);
dout_a : out unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
end ram_2c_2r_2w;
architecture Behavioral of ram_2c_2r_2w is
constant depth : integer := 2**addr_width;
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
shared variable RAM : RAMtype;
begin
process (clka)
begin
if clka'event and clka = '1' then
if en_a = '1' then
if we_a = '1' then
RAM(to_integer(addr_a)) := din_a;
end if;
dout_a <= RAM(to_integer(addr_a));
end if;
end if;
end process;
process (clkb)
begin
if clkb'event and clkb = '1' then
if en_b = '1' then
if we_b = '1' then
RAM(to_integer(addr_b)) := din_b;
end if;
dout_b <= RAM(to_integer(addr_b));
end if;
end if;
end process;
end Behavioral;
+150
View File
@@ -0,0 +1,150 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: testbench for embedded cpu with rom
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- 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
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
use std.textio.all; -- Imports the standard textio package.
library work;
ENTITY tb_j1 IS
END tb_j1;
ARCHITECTURE behavior OF tb_j1 IS
constant CLK_PERIOD : time := 10 ns;
-- Inputs
signal sys_clk_i : std_logic := '0';
signal sys_rst_i : std_logic := '1';
signal io_din : unsigned(15 downto 0) := (others => '0');
signal inst_din : unsigned(15 downto 0) := (others => '0');
signal data_din : unsigned(15 downto 0) := (others => '0');
-- Outputs
signal io_rd : std_logic;
signal io_wr : std_logic;
signal io_addr : unsigned(15 downto 0);
signal io_dout : unsigned(15 downto 0);
signal data_dout : unsigned(15 downto 0);
signal inst_addr : unsigned(12 downto 0);
signal data_addr : unsigned(12 downto 0);
signal data_we : std_logic;
signal data_en : std_logic;
type rom_t is array (integer range <>) of unsigned(15 downto 0);
signal rom : rom_t(0 to 15) :=
(
X"8123", -- 0000
X"0002", -- 0001
X"0005", -- 0002
X"8456", -- 0003
X"4008", -- 0004
X"0003", -- 0005
X"0000", -- 0006
X"0000", -- 0007
X"8456", -- 0008
X"8451", -- 0009
X"7000", -- 000A
X"0000", -- 000B
X"0000", -- 000C
X"0000", -- 000D
X"0000", -- 000E
X"0000" -- 000F
);
BEGIN
-- Instruction rom
process(sys_clk_i)
begin
if rising_edge(sys_clk_i) then
inst_din <= rom(to_integer(inst_addr(3 downto 0)));
end if;
end process;
uut: entity work.j1
PORT MAP
(
sys_clk_i => sys_clk_i,
sys_rst_i => sys_rst_i,
io_din => io_din,
io_rd => io_rd,
io_wr => io_wr,
io_addr => io_addr,
inst_din => inst_din,
inst_addr => inst_addr,
data_addr => data_addr,
data_we => data_we,
data_en => data_en,
data_din => data_din,
data_dout => data_dout
);
inst_ram: entity work.ram_2c_2r_2w
GENERIC MAP
(
addr_width => 13,
data_width => 16
)
PORT MAP(
clka => sys_clk_i,
clkb => sys_clk_i,
en_a => '1',
en_b => data_en,
we_a => '0',
we_b => data_we,
addr_a => (others => '0'), --inst_addr
addr_b => data_addr,
din_a => (others => '0'),
din_b => data_dout,
dout_a => open, -- inst_din
dout_b => data_din
);
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
sys_clk_i <= not sys_clk_i;
end process;
STIMULUS: process
begin
wait for 3*CLK_PERIOD;
sys_rst_i <= '0';
wait for 2*CLK_PERIOD;
wait for 1000*CLK_PERIOD;
assert false report "Test finished" severity error;
wait;
end process;
end behavior;