diff --git a/lib/CPUs/J1/doc/j1.pdf b/lib/CPUs/J1/doc/j1.pdf
new file mode 100644
index 0000000..188ac02
Binary files /dev/null and b/lib/CPUs/J1/doc/j1.pdf differ
diff --git a/lib/CPUs/J1/sim/tb_j1.do b/lib/CPUs/J1/sim/tb_j1.do
new file mode 100644
index 0000000..4fa1a55
--- /dev/null
+++ b/lib/CPUs/J1/sim/tb_j1.do
@@ -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
diff --git a/lib/CPUs/J1/sim/tb_j1.wave.do b/lib/CPUs/J1/sim/tb_j1.wave.do
new file mode 100644
index 0000000..58c0f66
--- /dev/null
+++ b/lib/CPUs/J1/sim/tb_j1.wave.do
@@ -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}
diff --git a/lib/CPUs/J1/src/core/j1.v b/lib/CPUs/J1/src/core/j1.v
new file mode 100644
index 0000000..861cb3c
--- /dev/null
+++ b/lib/CPUs/J1/src/core/j1.v
@@ -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
diff --git a/lib/CPUs/J1/src/core/j1.vhd b/lib/CPUs/J1/src/core/j1.vhd
new file mode 100644
index 0000000..d5c9f14
--- /dev/null
+++ b/lib/CPUs/J1/src/core/j1.vhd
@@ -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;
diff --git a/lib/CPUs/J1/src/core/ram_2c_2r_2w.vhd b/lib/CPUs/J1/src/core/ram_2c_2r_2w.vhd
new file mode 100644
index 0000000..23d8118
--- /dev/null
+++ b/lib/CPUs/J1/src/core/ram_2c_2r_2w.vhd
@@ -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 .
+--
+-- 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;
+
diff --git a/lib/CPUs/J1/src/tb_j1.vhd b/lib/CPUs/J1/src/tb_j1.vhd
new file mode 100644
index 0000000..8aa4c3c
--- /dev/null
+++ b/lib/CPUs/J1/src/tb_j1.vhd
@@ -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 .
+--
+-- 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;
diff --git a/lib/ac97_ctrl/todo.txt b/lib/ac97_ctrl/todo.txt
new file mode 100644
index 0000000..7abc706
--- /dev/null
+++ b/lib/ac97_ctrl/todo.txt
@@ -0,0 +1,2 @@
+2010-07-08
+- RX FIFO