-- $Id: pdp11_bram_memctl.vhd 784 2016-07-09 22:17:01Z mueller $
|
-- $Id: pdp11_bram_memctl.vhd 784 2016-07-09 22:17:01Z mueller $
|
--
|
--
|
-- Copyright 2015-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
-- Copyright 2015-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
--
|
--
|
-- This program is free software; you may redistribute and/or modify it under
|
-- This program is free software; you may redistribute and/or modify it under
|
-- the terms of the GNU General Public License as published by the Free
|
-- the terms of the GNU General Public License as published by the Free
|
-- Software Foundation, either version 2, or at your option any later version.
|
-- Software Foundation, either version 2, or at your option any later version.
|
--
|
--
|
-- This program is distributed in the hope that it will be useful, but
|
-- This program is distributed in the hope that it will be useful, but
|
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
-- for complete details.
|
-- for complete details.
|
--
|
--
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Module Name: pdp11_bram_memctl - syn
|
-- Module Name: pdp11_bram_memctl - syn
|
-- Description: pdp11: BRAM based memctl
|
-- Description: pdp11: BRAM based memctl
|
--
|
--
|
-- Dependencies: -
|
-- Dependencies: -
|
-- Test bench: -
|
-- Test bench: -
|
-- Target Devices: 7-Series
|
-- Target Devices: 7-Series
|
-- Tool versions: ise 14.7; viv 2014.4-2016.1; ghdl 0.31-0.33
|
-- Tool versions: ise 14.7; viv 2014.4-2016.1; ghdl 0.31-0.33
|
--
|
--
|
-- Revision History:
|
-- Revision History:
|
-- Date Rev Version Comment
|
-- Date Rev Version Comment
|
-- 2016-05-22 767 1.1.1 don't init N_REGS (vivado fix for fsm inference)
|
-- 2016-05-22 767 1.1.1 don't init N_REGS (vivado fix for fsm inference)
|
-- 2016-03-20 749 1.1 use ram_1swsr_wfirst_gen rather BRAM_SINGLE_MACRO
|
-- 2016-03-20 749 1.1 use ram_1swsr_wfirst_gen rather BRAM_SINGLE_MACRO
|
-- 2015-02-08 644 1.0 Initial version
|
-- 2015-02-08 644 1.0 Initial version
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
|
use work.slvtypes.all;
|
use work.slvtypes.all;
|
use work.memlib.all;
|
use work.memlib.all;
|
use work.pdp11.all;
|
use work.pdp11.all;
|
|
|
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
|
|
entity pdp11_bram_memctl is -- BRAM based memctl
|
entity pdp11_bram_memctl is -- BRAM based memctl
|
generic (
|
generic (
|
MAWIDTH : positive := 4; -- mux address width
|
MAWIDTH : positive := 4; -- mux address width
|
NBLOCK : positive := 11); -- number of 16 kByte blocks
|
NBLOCK : positive := 11); -- number of 16 kByte blocks
|
port (
|
port (
|
CLK : in slbit; -- clock
|
CLK : in slbit; -- clock
|
RESET : in slbit; -- reset
|
RESET : in slbit; -- reset
|
REQ : in slbit; -- request
|
REQ : in slbit; -- request
|
WE : in slbit; -- write enable
|
WE : in slbit; -- write enable
|
BUSY : out slbit; -- controller busy
|
BUSY : out slbit; -- controller busy
|
ACK_R : out slbit; -- acknowledge read
|
ACK_R : out slbit; -- acknowledge read
|
ACK_W : out slbit; -- acknowledge write
|
ACK_W : out slbit; -- acknowledge write
|
ACT_R : out slbit; -- signal active read
|
ACT_R : out slbit; -- signal active read
|
ACT_W : out slbit; -- signal active write
|
ACT_W : out slbit; -- signal active write
|
ADDR : in slv20; -- address
|
ADDR : in slv20; -- address
|
BE : in slv4; -- byte enable
|
BE : in slv4; -- byte enable
|
DI : in slv32; -- data in (memory view)
|
DI : in slv32; -- data in (memory view)
|
DO : out slv32 -- data out (memory view)
|
DO : out slv32 -- data out (memory view)
|
);
|
);
|
end pdp11_bram_memctl;
|
end pdp11_bram_memctl;
|
|
|
architecture syn of pdp11_bram_memctl is
|
architecture syn of pdp11_bram_memctl is
|
|
|
type state_type is (
|
type state_type is (
|
s_idle, -- s_idle: wait for req
|
s_idle, -- s_idle: wait for req
|
s_read0, -- s_read0
|
s_read0, -- s_read0
|
s_read1, -- s_read1
|
s_read1, -- s_read1
|
s_write -- s_write
|
s_write -- s_write
|
);
|
);
|
|
|
type regs_type is record
|
type regs_type is record
|
state : state_type; -- state
|
state : state_type; -- state
|
muxaddr : slv(MAWIDTH-1 downto 0); -- mux addr buffer
|
muxaddr : slv(MAWIDTH-1 downto 0); -- mux addr buffer
|
celladdr : slv12; -- cell addr buffer
|
celladdr : slv12; -- cell addr buffer
|
cellen : slv(2**MAWIDTH-1 downto 0);-- cell enables
|
cellen : slv(2**MAWIDTH-1 downto 0);-- cell enables
|
cellwe : slv4; -- write enables
|
cellwe : slv4; -- write enables
|
dibuf : slv32; -- data in buffer
|
dibuf : slv32; -- data in buffer
|
dobuf : slv32; -- data out buffer
|
dobuf : slv32; -- data out buffer
|
ackr : slbit; -- signal ack_r
|
ackr : slbit; -- signal ack_r
|
end record regs_type;
|
end record regs_type;
|
|
|
constant muxaddrzero : slv(MAWIDTH-1 downto 0) := (others=>'0');
|
constant muxaddrzero : slv(MAWIDTH-1 downto 0) := (others=>'0');
|
constant cellenzero : slv(2**MAWIDTH-1 downto 0) := (others=>'0');
|
constant cellenzero : slv(2**MAWIDTH-1 downto 0) := (others=>'0');
|
constant regs_init : regs_type := (
|
constant regs_init : regs_type := (
|
s_idle, -- state
|
s_idle, -- state
|
muxaddrzero, -- muxaddr
|
muxaddrzero, -- muxaddr
|
(others=>'0'), -- celladdr
|
(others=>'0'), -- celladdr
|
cellenzero, -- cellen
|
cellenzero, -- cellen
|
(others=>'0'), -- cellwe
|
(others=>'0'), -- cellwe
|
(others=>'0'), -- dibuf
|
(others=>'0'), -- dibuf
|
(others=>'0'), -- dobuf
|
(others=>'0'), -- dobuf
|
'0' -- ackr
|
'0' -- ackr
|
);
|
);
|
|
|
signal R_REGS : regs_type := regs_init;
|
signal R_REGS : regs_type := regs_init;
|
signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
|
signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
|
|
|
type mem_do_type is array (NBLOCK-1 downto 0) of slv32;
|
type mem_do_type is array (NBLOCK-1 downto 0) of slv32;
|
signal MEM_DO : mem_do_type := (others=> (others => '0'));
|
signal MEM_DO : mem_do_type := (others=> (others => '0'));
|
|
|
begin
|
begin
|
|
|
assert MAWIDTH <= 8
|
assert MAWIDTH <= 8
|
report "assert(MAWIDTH <= 8)" severity failure;
|
report "assert(MAWIDTH <= 8)" severity failure;
|
assert NBLOCK <= 2**MAWIDTH
|
assert NBLOCK <= 2**MAWIDTH
|
report "assert(NBLOCK <= 2**MAWIDTH)" severity failure;
|
report "assert(NBLOCK <= 2**MAWIDTH)" severity failure;
|
|
|
-- generate memory array
|
-- generate memory array
|
-- 4 colums, one for each byte of the 32 bit word
|
-- 4 colums, one for each byte of the 32 bit word
|
-- NBLOCK rows, as many as one can afford ...
|
-- NBLOCK rows, as many as one can afford ...
|
|
|
MARRAY: for row in NBLOCK-1 downto 0 generate
|
MARRAY: for row in NBLOCK-1 downto 0 generate
|
MROW: for col in 3 downto 0 generate
|
MROW: for col in 3 downto 0 generate
|
begin
|
begin
|
MCELL : ram_1swsr_wfirst_gen
|
MCELL : ram_1swsr_wfirst_gen
|
generic map (
|
generic map (
|
AWIDTH => 12, -- 4 Kb blocks
|
AWIDTH => 12, -- 4 Kb blocks
|
DWIDTH => 8) -- byte wide
|
DWIDTH => 8) -- byte wide
|
port map (
|
port map (
|
CLK => CLK,
|
CLK => CLK,
|
EN => R_REGS.cellen(row),
|
EN => R_REGS.cellen(row),
|
WE => R_REGS.cellwe(col),
|
WE => R_REGS.cellwe(col),
|
ADDR => R_REGS.celladdr,
|
ADDR => R_REGS.celladdr,
|
DI => R_REGS.dibuf(8*col+7 downto 8*col),
|
DI => R_REGS.dibuf(8*col+7 downto 8*col),
|
DO => MEM_DO(row)(8*col+7 downto 8*col)
|
DO => MEM_DO(row)(8*col+7 downto 8*col)
|
);
|
);
|
end generate MROW;
|
end generate MROW;
|
end generate MARRAY;
|
end generate MARRAY;
|
|
|
proc_regs: process (CLK)
|
proc_regs: process (CLK)
|
begin
|
begin
|
|
|
if rising_edge(CLK) then
|
if rising_edge(CLK) then
|
if RESET = '1' then
|
if RESET = '1' then
|
R_REGS <= regs_init;
|
R_REGS <= regs_init;
|
else
|
else
|
R_REGS <= N_REGS;
|
R_REGS <= N_REGS;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
end process proc_regs;
|
end process proc_regs;
|
|
|
proc_next: process (R_REGS, ADDR, DI, REQ, WE, BE, MEM_DO)
|
proc_next: process (R_REGS, ADDR, DI, REQ, WE, BE, MEM_DO)
|
|
|
variable r : regs_type := regs_init;
|
variable r : regs_type := regs_init;
|
variable n : regs_type := regs_init;
|
variable n : regs_type := regs_init;
|
variable ibusy : slbit := '0';
|
variable ibusy : slbit := '0';
|
variable iackw : slbit := '0';
|
variable iackw : slbit := '0';
|
variable iactr : slbit := '0';
|
variable iactr : slbit := '0';
|
variable iactw : slbit := '0';
|
variable iactw : slbit := '0';
|
begin
|
begin
|
|
|
r := R_REGS;
|
r := R_REGS;
|
n := R_REGS;
|
n := R_REGS;
|
n.ackr := '0';
|
n.ackr := '0';
|
|
|
ibusy := '0';
|
ibusy := '0';
|
iackw := '0';
|
iackw := '0';
|
iactr := '0';
|
iactr := '0';
|
iactw := '0';
|
iactw := '0';
|
|
|
case r.state is
|
case r.state is
|
when s_idle => -- s_idle: wait for req
|
when s_idle => -- s_idle: wait for req
|
n.cellen := (others=>'0');
|
n.cellen := (others=>'0');
|
n.cellwe := (others=>'0');
|
n.cellwe := (others=>'0');
|
if REQ = '1' then
|
if REQ = '1' then
|
n.muxaddr := ADDR(MAWIDTH-1+12 downto 12);
|
n.muxaddr := ADDR(MAWIDTH-1+12 downto 12);
|
n.celladdr := ADDR(11 downto 0);
|
n.celladdr := ADDR(11 downto 0);
|
n.dibuf := DI;
|
n.dibuf := DI;
|
n.cellen(to_integer(unsigned(ADDR(MAWIDTH-1+12 downto 12)))) := '1';
|
n.cellen(to_integer(unsigned(ADDR(MAWIDTH-1+12 downto 12)))) := '1';
|
if WE = '1' then
|
if WE = '1' then
|
n.cellwe := BE;
|
n.cellwe := BE;
|
n.state := s_write;
|
n.state := s_write;
|
else
|
else
|
n.state := s_read0;
|
n.state := s_read0;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
when s_read0 => -- s_read0
|
when s_read0 => -- s_read0
|
ibusy := '1';
|
ibusy := '1';
|
iactr := '1';
|
iactr := '1';
|
n.state := s_read1;
|
n.state := s_read1;
|
|
|
when s_read1 => -- s_read1
|
when s_read1 => -- s_read1
|
ibusy := '1';
|
ibusy := '1';
|
iactr := '1';
|
iactr := '1';
|
n.dobuf := MEM_DO(to_integer(unsigned(r.muxaddr)));
|
n.dobuf := MEM_DO(to_integer(unsigned(r.muxaddr)));
|
n.ackr := '1';
|
n.ackr := '1';
|
n.state := s_idle;
|
n.state := s_idle;
|
|
|
when s_write => -- s_write
|
when s_write => -- s_write
|
ibusy := '1';
|
ibusy := '1';
|
iactw := '1';
|
iactw := '1';
|
iackw := '1';
|
iackw := '1';
|
n.cellwe := (others=>'0');
|
n.cellwe := (others=>'0');
|
n.state := s_idle;
|
n.state := s_idle;
|
|
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
|
|
N_REGS <= n;
|
N_REGS <= n;
|
|
|
BUSY <= ibusy;
|
BUSY <= ibusy;
|
ACK_R <= r.ackr;
|
ACK_R <= r.ackr;
|
ACK_W <= iackw;
|
ACK_W <= iackw;
|
ACT_R <= iactr;
|
ACT_R <= iactr;
|
ACT_W <= iactw;
|
ACT_W <= iactw;
|
DO <= r.dobuf;
|
DO <= r.dobuf;
|
end process proc_next;
|
end process proc_next;
|
|
|
end syn;
|
end syn;
|
|
|