1
0
mirror of https://github.com/j-core/j-core-ice40.git synced 2026-04-24 19:33:35 +00:00

Sync RAM register file implemntation

This commit is contained in:
J
2019-03-13 17:05:56 -04:00
parent fb8fdd41c7
commit c611736bad
7 changed files with 320 additions and 87 deletions

View File

@@ -166,8 +166,11 @@ begin
mem.lock <= pipeline_r.ex1.mem_lock;
mem.size <= pipeline_r.ex1.mem_size;
reg.num_w <= pipeline_r.wb3.regnum_w;
reg.num_x <= pipeline_r.ex1.regnum_x;
reg.num_y <= pipeline_r.ex1.regnum_y;
-- Make read regnum valid at the end of decode, allow clocked read regfile
reg.num_x <= ex.regnum_x;
reg.num_y <= ex.regnum_y;
-- reg.num_x <= pipeline_r.ex1.regnum_x;
-- reg.num_y <= pipeline_r.ex1.regnum_y;
reg.num_z <= pipeline_r.ex1.regnum_z;
buses.x_sel <= pipeline_r.ex1.xbus_sel;
buses.y_sel <= pipeline_r.ex1.ybus_sel;

View File

@@ -2,7 +2,7 @@
rm *.o *.cf
ghdl -a cpu2j0_pkg.vhd components_pkg.vhd mult_pkg.vhd decode_pkg.vhd decode_body.vhd datapath_pkg.vhd cpu.vhd decode.vhd decode_core.vhd decode_table.vhd decode_table_reverse.vhd datapath.vhd register_file.vhd mult.vhd
ghdl -a cpu2j0_pkg.vhd components_pkg.vhd mult_pkg.vhd decode_pkg.vhd decode_body.vhd datapath_pkg.vhd cpu.vhd decode.vhd decode_core.vhd decode_table.vhd decode_table_reverse.vhd datapath.vhd register_file_sync.vhd mult.vhd
ghdl -a data_bus_pkg.vhd monitor_pkg.vhd ram_init.vhd lattice_ebr.vhd bus_monitor.vhd timeout_cnt.vhd cpu_simple_sram.vhd
@@ -12,4 +12,5 @@ ghdl -a cpu_lattice.vhd lattice_tb.vhd
ghdl -e lattice_tb
./lattice_tb --stop-time=2700ns --wave=out.ghw
./lattice_tb --stop-time=2700ns --wave=out.ghw --ieee-asserts=disable-at-0 > /dev/null
./lattice_tb --stop-time=2ms --ieee-asserts=disable-at-0

BIN
ram.img

Binary file not shown.

View File

@@ -102,12 +102,12 @@ package bootrom is
x"410b6483",
x"60834f26",
x"000b68f6",
x"000010dc",
x"0000111c",
x"d0034f22",
x"400b0009",
x"4f26000b",
x"00090009",
x"000010f4",
x"00001134",
x"000b0009",
x"d101412b",
x"00090009",
@@ -186,7 +186,7 @@ package bootrom is
x"6bf66af6",
x"69f6000b",
x"68f60009",
x"00001194",
x"000011d4",
x"2f86e800",
x"2f966953",
x"2fa66a53",
@@ -232,7 +232,7 @@ package bootrom is
x"68f60009",
x"0000016c",
x"000002d4",
x"00001194",
x"000011d4",
x"00000184",
x"2f862f96",
x"2fa62fb6",
@@ -334,8 +334,8 @@ package bootrom is
x"68f60009",
x"0000016c",
x"000002d4",
x"00001140",
x"00001194",
x"00001180",
x"000011d4",
x"2f862f96",
x"2fa62fb6",
x"2fc62fd6",
@@ -526,15 +526,15 @@ package bootrom is
x"00000184",
x"0000016c",
x"00000310",
x"0000114c",
x"0000118c",
x"00000d7c",
x"000001e0",
x"00000390",
x"00000ed0",
x"00000224",
x"000002d4",
x"00001144",
x"00001194",
x"00001184",
x"000011d4",
x"00000fac",
x"00000f40",
x"00000d7c",
@@ -631,12 +631,12 @@ package bootrom is
x"00000390",
x"00000f40",
x"00000310",
x"00001150",
x"000011ec",
x"00001190",
x"0000122c",
x"000001e0",
x"00000d88",
x"00001024",
x"0000114c",
x"0000118c",
x"2f862448",
x"2f962fa6",
x"2fb62fc6",
@@ -706,12 +706,12 @@ package bootrom is
x"68f60009",
x"0000016c",
x"000002d4",
x"000011bc",
x"000011a8",
x"000011fc",
x"000011e8",
x"00000224",
x"00001164",
x"00001168",
x"00001194",
x"000011a4",
x"000011a8",
x"000011d4",
x"00000528",
x"2f866043",
x"2f964009",
@@ -797,7 +797,7 @@ package bootrom is
x"6af669f6",
x"000b68f6",
x"0000016c",
x"00001194",
x"000011d4",
x"00000ed0",
x"00000184",
x"00000528",
@@ -820,7 +820,7 @@ package bootrom is
x"d00164f2",
x"400b0009",
x"00000b0c",
x"0000129c",
x"000012dc",
x"2f062f16",
x"e0f0400e",
x"e0052f06",
@@ -868,7 +868,7 @@ package bootrom is
x"70c05101",
x"6002002b",
x"00090009",
x"00001244",
x"00001284",
x"ef046ff2",
x"e0006002",
x"402b0009",
@@ -941,18 +941,18 @@ package bootrom is
x"f80007ff",
x"402b400b",
x"c3200009",
x"00001284",
x"000012c4",
x"0000fb00",
x"00008900",
x"00008b00",
x"0000f000",
x"0000a000",
x"0000f0ff",
x"00001244",
x"00001284",
x"0000b000",
x"0000ff00",
x"0000c300",
x"000012a0",
x"000012e0",
x"00000d3a",
x"e1163416",
x"8d2de000",
@@ -980,8 +980,8 @@ package bootrom is
x"5116e004",
x"2512000b",
x"00090009",
x"00001244",
x"00001284",
x"000012c4",
x"e1163416",
x"8d2ce000",
x"6243c702",
@@ -1007,13 +1007,13 @@ package bootrom is
x"1154d103",
x"1156e004",
x"000b0009",
x"00001244",
x"00001284",
x"000012c4",
x"24488901",
x"d1021145",
x"d102412b",
x"00090009",
x"00001284",
x"000012c4",
x"00000d3a",
x"d1056211",
x"22288904",
@@ -1021,8 +1021,8 @@ package bootrom is
x"2321e200",
x"2121000b",
x"00090009",
x"000012a0",
x"00001284",
x"000012e0",
x"000012c4",
x"d001402b",
x"00090009",
x"000009dc",
@@ -1036,8 +1036,8 @@ package bootrom is
x"91032212",
x"2312000b",
x"00090088",
x"000011f0",
x"00001240",
x"00001230",
x"00001280",
x"abcd0000",
x"000b0009",
x"2f866843",
@@ -1052,39 +1052,55 @@ package bootrom is
x"60804f26",
x"6af669f6",
x"000b68f6",
x"000010dc",
x"0000111c",
x"d1012142",
x"000b0009",
x"abcd0000",
x"2f86e440",
x"2f96d815",
x"4f22480b",
x"7ffcd014",
x"d914400b",
x"0009480b",
x"e442d413",
x"2f962fa6",
x"d8244f22",
x"480b7ffc",
x"d023d924",
x"400b0009",
x"480be442",
x"d422490b",
x"0009d422",
x"490b0009",
x"d412490b",
x"0009d912",
x"480be450",
x"e1002f12",
x"61f23197",
x"890261f2",
x"aff97101",
x"480be455",
x"e1002f12",
x"61f23197",
x"890261f2",
x"aff97101",
x"9403480b",
x"0009afea",
x"e10000aa",
x"e1009232",
x"2f1261f2",
x"31278904",
x"61f27101",
x"2f12aff8",
x"0009480b",
x"e455e100",
x"92252f12",
x"61f23127",
x"890461f2",
x"71012f12",
x"aff80009",
x"da14941b",
x"480be900",
x"2f9261f2",
x"31a78904",
x"61f27101",
x"2f12aff8",
x"0009480b",
x"e4552f92",
x"61f231a7",
x"890461f2",
x"71012f12",
x"aff80009",
x"9404480b",
x"0009afe7",
x"0009031f",
x"00aa0009",
x"0000105c",
x"0000113c",
x"0000117c",
x"00001028",
x"000011d0",
x"000011f4",
x"0001869f",
x"00001210",
x"00001234",
x"00124f7f",
x"d104644c",
x"5012c808",
x"8bfcd102",
@@ -1103,8 +1119,8 @@ package bootrom is
x"64036083",
x"4f26000b",
x"68f60009",
x"000010f4",
x"000010dc",
x"00001134",
x"0000111c",
x"d102e202",
x"1123000b",
x"00090009",
@@ -1141,11 +1157,11 @@ package bootrom is
x"00000006",
x"00000007",
x"00000007",
x"0000116c",
x"00001174",
x"0000117c",
x"00001184",
x"0000118c",
x"000011ac",
x"000011b4",
x"000011bc",
x"000011c4",
x"000011cc",
x"47444220",
x"53747562",
x"20666f72",
@@ -1161,17 +1177,17 @@ package bootrom is
x"616e6765",
x"7365743a",
x"20202031",
x"313a6161",
x"34323266",
x"33346365",
x"34630a62",
x"323a3039",
x"36623435",
x"36666263",
x"61370a62",
x"75696c64",
x"3a205361",
x"74204d61",
x"72202039",
x"2031383a",
x"33393a32",
x"31204553",
x"3a205765",
x"64204d61",
x"72203133",
x"2031373a",
x"30333a32",
x"36204544",
x"54203230",
x"31390a00",
others => x"00000000" );

View File

@@ -109,8 +109,10 @@ architecture two_bank of register_file is
signal bank_a, bank_b : ram_type := (others => (others => '0'));
signal reg0 : data_t;
signal da : std_logic_vector(REG_WIDTH-1 downto 0);
signal db : std_logic_vector(REG_WIDTH-1 downto 0);
signal da : std_logic_vector(REG_WIDTH-1 downto 0);
signal db : std_logic_vector(REG_WIDTH-1 downto 0);
signal aa : std_logic_vector(ADDR_WIDTH-1 downto 0);
signal ab : std_logic_vector(ADDR_WIDTH-1 downto 0);
signal ex_pipes : ex_pipeline_t;
signal wb_pipe : reg_pipe_t;
@@ -124,19 +126,18 @@ begin
ex_pipes(0).addr <= w_addr_ex;
ex_pipes(0).data <= din_ex;
dout_a <= read_with_forwarding(addr_ra, da, wb_pipe, ex_pipes);
dout_b <= read_with_forwarding(addr_rb, db, wb_pipe, ex_pipes);
-- Async read (trasparent) register file. Later clocked address
da <= bank_a(to_reg_index(aa));
db <= bank_b(to_reg_index(ab));
dout_a <= read_with_forwarding( aa, da, wb_pipe, ex_pipes);
dout_b <= read_with_forwarding( ab, db, wb_pipe, ex_pipes);
dout_0 <= read_with_forwarding(ZERO_ADDR, reg0, wb_pipe, ex_pipes);
process (clk, rst, ce, wb_pipe, ex_pipes)
variable addr : integer;
variable data : data_t;
begin
if (falling_edge(clk)) then
da <= bank_a(to_reg_index(addr_ra));
db <= bank_b(to_reg_index(addr_rb));
end if;
if rst = '1' then
addr := 0;
data := (others => '0');
@@ -151,6 +152,12 @@ begin
data => (others => '0'),
addr => (others => '0'));
elsif (rising_edge(clk) and ce = '1') then
aa <= addr_ra;
ab <= addr_rb;
-- Sync read (clocked) register file. Early address
-- da <= bank_a(to_reg_index(addr_ra));
-- db <= bank_b(to_reg_index(addr_rb));
-- the decoder should never schedule a write to a register for both Z and
-- W bus at the same time
assert (wb_pipe.en and ex_pipes(2).en) = '0'
@@ -170,6 +177,14 @@ begin
if (addr = 0) then
reg0 <= data;
end if;
-- Sync read bypass
-- if (addr = to_reg_index(addr_ra)) then
-- da <= data;
-- end if;
-- if (addr = to_reg_index(addr_rb)) then
-- db <= data;
-- end if;
end if;
ex_pipes(2) <= ex_pipes(1);
ex_pipes(1) <= ex_pipes(0);

193
register_file_sync.vhd Normal file
View File

@@ -0,0 +1,193 @@
-- A Register File with 2 write ports and 2 read ports built out of
-- 2 RAM blocks with 1 read and 1 independant write port. Register 0
-- also has independant ouput. 32 regs x 32 bits by default, one write clock.
--
-- Both write ports actually write to the same RAM blocks by delaying EX stage
-- writes to the WB stage and assuming that the decoder will never schedule
-- register writes for both Z and W busses in same ID stage.
--
-- To delay EX stage writes, a pipeline of 2 pending writes is kept. To service
-- a read, either the data in the EX pipeline or the current WB write value
-- may be returned instead of the data in the RAM block. Servicing reads from
-- the current WB write value implements W bus forwarding.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity register_file is
generic (
ADDR_WIDTH : integer := 5;
NUM_REGS : integer := 32;
REG_WIDTH : integer := 32);
port (
clk : in std_logic;
rst : in std_logic;
ce : in std_logic;
addr_ra : in std_logic_vector(ADDR_WIDTH-1 downto 0);
dout_a : out std_logic_vector(REG_WIDTH-1 downto 0);
addr_rb : in std_logic_vector(ADDR_WIDTH-1 downto 0);
dout_b : out std_logic_vector(REG_WIDTH-1 downto 0);
dout_0 : out std_logic_vector(REG_WIDTH-1 downto 0);
we_wb : in std_logic;
w_addr_wb : in std_logic_vector(ADDR_WIDTH-1 downto 0);
din_wb : in std_logic_vector(REG_WIDTH-1 downto 0);
we_ex : in std_logic;
w_addr_ex : in std_logic_vector(ADDR_WIDTH-1 downto 0);
din_ex : in std_logic_vector(REG_WIDTH-1 downto 0);
-- wr_data_o exposes the data about to be written to the
-- register memories
wr_data_o : out std_logic_vector(REG_WIDTH-1 downto 0)
);
subtype addr_t is std_logic_vector(ADDR_WIDTH-1 downto 0);
subtype data_t is std_logic_vector(REG_WIDTH-1 downto 0);
type reg_pipe_t is
record
en : std_logic;
data : data_t;
addr : addr_t;
end record;
type ex_pipeline_t is array(0 to 2) of reg_pipe_t;
function pipe_matches(pipe : reg_pipe_t; addr : addr_t)
return boolean is
begin
return pipe.en = '1' and pipe.addr = addr;
end;
function read_with_forwarding(addr : addr_t; bank_data : data_t;
wb_pipe : reg_pipe_t;
ex_pipes : ex_pipeline_t)
return std_logic_vector is
begin
-- The goal here is to read the most recent value for a register.
-- (I believe the order of the wb_pipe and ex_pipes(1) checks doesn't
-- matter and can be reversed because they cannot both be writing to the
-- same register. Register conflict detection prevents that.)
-- forward from W bus writes occuring this cycle
if (pipe_matches(wb_pipe, addr)) then
return wb_pipe.data;
-- ex_pipes(1) and ex_pipes(2) are "already written" values that should be
-- returned before the bank data. Check ex_pipes(1) first as it is the more
-- recent write.
elsif (pipe_matches(ex_pipes(1), addr)) then
return ex_pipes(1).data;
elsif (pipe_matches(ex_pipes(2), addr)) then
return ex_pipes(2).data;
else
-- no matching pending writes in the pipeline, return bank data
return bank_data;
end if;
end;
function to_reg_index(addr : addr_t)
return integer is
variable ret : integer range 0 to 31;
begin
ret := to_integer(unsigned(addr));
if ret >= NUM_REGS then
report "Register out of range";
ret := 0;
end if;
return ret;
end;
end register_file;
architecture two_bank of register_file is
constant ZERO_ADDR : addr_t := (others => '0');
type ram_type is array(0 to NUM_REGS - 1) of data_t;
signal bank_a, bank_b : ram_type := (others => (others => '0'));
signal reg0 : data_t;
signal da : std_logic_vector(REG_WIDTH-1 downto 0);
signal db : std_logic_vector(REG_WIDTH-1 downto 0);
signal aa : std_logic_vector(ADDR_WIDTH-1 downto 0);
signal ab : std_logic_vector(ADDR_WIDTH-1 downto 0);
signal ex_pipes : ex_pipeline_t;
signal wb_pipe : reg_pipe_t;
begin
wb_pipe.en <= we_wb;
wb_pipe.addr <= w_addr_wb;
wb_pipe.data <= din_wb;
ex_pipes(0).en <= we_ex;
ex_pipes(0).addr <= w_addr_ex;
ex_pipes(0).data <= din_ex;
-- Async read (trasparent) register file. Later clocked address
-- da <= bank_a(to_reg_index(aa));
-- db <= bank_b(to_reg_index(ab));
dout_a <= read_with_forwarding( aa, da, wb_pipe, ex_pipes);
dout_b <= read_with_forwarding( ab, db, wb_pipe, ex_pipes);
dout_0 <= read_with_forwarding(ZERO_ADDR, reg0, wb_pipe, ex_pipes);
process (clk, rst, ce, wb_pipe, ex_pipes)
variable addr : integer;
variable data : data_t;
begin
if rst = '1' then
addr := 0;
data := (others => '0');
wr_data_o <= (others => '0');
reg0 <= (others => '0');
ex_pipes(1) <= (
en => '0',
data => (others => '0'),
addr => (others => '0'));
ex_pipes(2) <= (
en => '0',
data => (others => '0'),
addr => (others => '0'));
elsif (rising_edge(clk) and ce = '1') then
aa <= addr_ra;
ab <= addr_rb;
-- Sync read (clocked) register file. Early address
da <= bank_a(to_reg_index(addr_ra));
db <= bank_b(to_reg_index(addr_rb));
-- the decoder should never schedule a write to a register for both Z and
-- W bus at the same time
assert (wb_pipe.en and ex_pipes(2).en) = '0'
report "Write clash detected" severity warning;
addr := to_reg_index(wb_pipe.addr);
data := wb_pipe.data;
if (ex_pipes(2).en = '1') then
addr := to_reg_index(ex_pipes(2).addr);
data := ex_pipes(2).data;
end if;
wr_data_o <= (others => '0');
if ((wb_pipe.en or ex_pipes(2).en) = '1') then
wr_data_o <= data;
bank_a(addr) <= data;
bank_b(addr) <= data;
if (addr = 0) then
reg0 <= data;
end if;
-- Sync read bypass
if (addr = to_reg_index(addr_ra)) then
da <= data;
end if;
if (addr = to_reg_index(addr_rb)) then
db <= data;
end if;
end if;
ex_pipes(2) <= ex_pipes(1);
ex_pipes(1) <= ex_pipes(0);
end if;
end process;
end architecture;

View File

@@ -103,10 +103,15 @@ main_sh (void)
putstr (version_string);
led(0x50);
for (i=0; i<800; i++) {}
led(0x55);
for (i=0; i<800; i++) {}
led(0xaa);
for (;;) {
for (i=0; i<100000; i++) {}
for (i=0; i<1200000; i++) {}
led(0x55);
for (i=0; i<100000; i++) {}
for (i=0; i<1200000; i++) {}
led(0xaa);
}
}