\subsubsection{BRAMCore}
\index{BRAMCore (package}
%\index{Xilinx!BRAMCore (package)}
\label{sec-BRAMCore}


{\bf Package}

\begin{verbatim}
import BRAMCore :: * ;
\end{verbatim}



{\bf Description}

The \te{BRAMCore} package, along with the \te{BRAM} package (Section
\ref{sec-BRAM}) provides types, interfaces, and modules to support
FPGA BlockRAMS.  Specific tools may determine whether modules are
mapped to  appropriate BRAM cells during synthesis.

Most designs should use the  the \te{BRAM} package instead of
\te{BRAMCore}, as the \te{BRAM} package provides implicit conditions
provided by  FIFO wrappers.
The \te{BRAMCore} package should be used only if you want the
low-level core BRAM modules without  implicit conditions.

The \te{BRAMCore}  package contains the low-level wrappers to the BRAM
Verilog and Bluesim modules.  Components are provided for   single and
dual port,  byte-enabled,  loadable, and dual clock versions.



{\bf Interfaces and Methods}

\index{BRAM\_PORT@\te{BRAM\_PORT} (interface type)}
%\index{BRAM@\te{BRAM} (interface type)}
\index{BRAM\_DUAL\_PORT@\te{BRAM\_DUAL\_PORT} (interface type)}

The \te{BRAMCore} package defines four  variations of a BRAM 
interface to support  single
and dual port BRAMs, as well as byte-enabled BRAMs.

The \te{BRAM\_PORT} interface declares two methods; an Action method
\te{put}, and a value method \te{read}.

The \te{BRAM\_DUAL\_PORT} interface is defined as two \te{BRAM\_PORT}
subinterfaces, one for each port.

\begin{tabular}{|p{.4in}|p{.5 in}|p{1.2 in}|p{.5in}|p{2.5 in}|}
\hline
\multicolumn{5}{|c|}{BRAM\_PORT Interface}\\
\hline
\multicolumn{3}{|c|}{Method}&\multicolumn{2}{|c|}{Arguments}\\
\hline
Name & Type & Description& Name &\multicolumn{1}{|c|}{Description} \\
\hline
\hline 
\te{put}&\te{Action}&Read or write values in the 
BRAM.&\te{write}& Write enable for the port; if \te{True} the action
is write, if \te{False}, the action is  read.\\
\cline{4-5}
&&&\te{address}&Index of the element, with a datatype of \te{addr}. \\
\cline{4-5}
&&&\te{datain}& Value to be written, with a datatype of \te{data}. This value is ignored if the action is read.\\
\hline
\te{read}&\it{data}&Returns a value of  type \te{data}.  & &\\
\hline
\end{tabular}

\begin{verbatim}
(* always_ready *)
interface BRAM_PORT#(type addr, type data);
   method Action put(Bool write, addr address, data datain);
   method data   read();
endinterface: BRAM_PORT
\end{verbatim}

\begin{verbatim}
interface BRAM_DUAL_PORT#(type addr, type data);
   interface BRAM_PORT#(addr, data) a;
   interface BRAM_PORT#(addr, data) b;
endinterface
\end{verbatim}

{\bf Byte-enabled Interfaces}

The \te{BRAM\_PORT\_BE} and
\te{BRAM\_DUAL\_PORT\_BE} interfaces are the byte-enabled  versions of the
BRAM interfaces. 
In this version, the  argument \te{writen} is of type
\te{Bit\#(n)}, where  \te{n} is  the number of byte-enables.  Your
synthesis tools and targeted technology determine the restriction of
data size and byte enable size.  If $n = 0$, the action is a read.  

The \te{BRAM\_DUAL\_PORT\_BE} interface is defined as two \te{BRAM\_PORT\_BE}
subinterfaces, one for each port.


\begin{tabular}{|p{.4in}|p{.5 in}|p{1.2 in}|p{.5in}|p{2.5 in}|}
\hline
\multicolumn{5}{|c|}{BRAM\_PORT\_BE Interface}\\
\hline
\multicolumn{3}{|c|}{Method}&\multicolumn{2}{|c|}{Arguments}\\
\hline
Name & Type & Description& Name &\multicolumn{1}{|c|}{Description} \\
\hline
\hline 
\te{put}&\te{Action}&Read or write  values in the
BRAM.  &\te{writeen}& Byte-enable for the port; if \te{n} != 0 write the
specified bytes,  if \te{n} = 0 read.  \\
\cline{4-5}
&&&\te{address}&Index of the elements to be read or written, with a datatype of \te{addr}. \\
\cline{4-5}
&&&\te{datain}& Value to be written, with a datatype of \te{data}.
This value is ignored if the action is read.\\
\hline
\te{read}&\it{data}&Returns a value of  type \te{data}.&&\\
\hline
\end{tabular}



\begin{verbatim}
(* always_ready *)
interface BRAM_PORT_BE#(type addr, type data, numeric type n);
   method Action put(Bit#(n) writeen, addr address, data datain);
   method data   read();
endinterface: BRAM_PORT_BE
\end{verbatim}

\begin{verbatim}
interface BRAM_DUAL_PORT_BE#(type addr, type data, numeric type n);
   interface BRAM_PORT_BE#(addr, data, n) a;
   interface BRAM_PORT_BE#(addr, data, n) b;
endinterface
\end{verbatim}


{\bf Modules}

The \te{BRAMCore} package provides 1 and 2 port BRAM core modules, in both
write-enabled and byte-enabled versions.  Note that there are no
implicit conditions on the methods of these modules; if these are
required consider using the modules in the \te{BRAM} package (Section
\ref{sec-BRAM}).  


The \te{BRAMCore} package requires the caller to
 ensure the correct cycle to capture the read data, as
 determined by  the \te{hasOutputRegister} flag.  If \te{hasOutputRegister} 
is \te{True}, both the read address and the read data are registered;
if \te{False}, only the read address is registered.

\begin{itemize}
\item If the output is registered (\te{hasOutputRegister} is \te{True}), the latency is 2; the read data is
available 2 cycles after the request. 
\item If the output is not registered (\te{hasOutputRegister} is \te{False}), the latency is 1; the read data
is available 1 cycle after the request.
\end{itemize}

The other argument  required is  \te{memSize},  an \te{Integer} 
specifying the memory size in number of words of type \te{data}.  


 The loadable BRAM modules require two additional arguments:
\begin{itemize}
\item \te{file} is a \te{String} containing the name of the load file.
\item \te{binary} is a \te{Bool} indicating whether 
 the data type of the load file is binary (\te{True}) or
hex (\te{False}).
\end{itemize}


\index{mkBRAMCore1@\te{mkBRAMCore1} (module)}
\index[function]{BRAM!mkBRAMCore1}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore1} &Single port BRAM \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore1#(Integer memSize,
               Bool hasOutputRegister) 
               (BRAM_PORT#(addr, data))
   provisos(Bits#(addr, addr_sz), Bits#(data, data_sz));
\end{libverbatim}
\\
\hline
\end{tabular}


\index{mkBRAMCore1BE@\te{mkBRAMCore1BE} (module)}
\index[function]{BRAM!mkBRAMCore1BE}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore1BE} &Byte-enabled, single port BRAM. \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore1BE#(Integer memSize,
                  Bool hasOutputRegister ) 
                 (BRAM_PORT_BE#(addr, data, n))
   provisos(Bits#(addr, addr_sz), Bits#(data, data_sz),
            Div#(data_sz, n, chunk_sz), 
            Mul#(chunk_sz, n, data_sz));
\end{libverbatim}
\\
\hline
\end{tabular}

% The \te{file} provides the initial contents of the BRAM.  If
% \te{binary} is \te{True} it is a binary file, if \te{False} it is a
% hex file.

\index{mkBRAMCore1Load@\te{mkBRAMCore1Load} (module)}
\index[function]{BRAM!mkBRAMCore1Load}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore1Load} &Loadable, single port BRAM where the initial
contents are in \te{file}.  The parameter \te{binary} indicates whether the
contents of \te{file} are  binary (\te{True}) or hex (\te{False}). \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore1Load#(Integer memSize, 
                        Bool hasOutputRegister,
                        String file, Bool binary )
                       (BRAM_PORT#(addr, data))
   provisos(Bits#(addr, addr_sz), Bits#(data, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}

\index{mkBRAMCore1BELoad@\te{mkBRAMCore1BELoad} (module)}
\index[function]{BRAM!mkBRAMCore1BELoad}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore1BELoad} &Loadable, single port, byte-enabled BRAM. \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore1BELoad#(Integer memSize,
                          Bool hasOutputRegister,
                          String file, Bool binary) 
                         (BRAM_PORT_BE#(addr, data, n))
   provisos(Bits#(addr, addr_sz), Bits#(data, data_sz),
            Div#(data_sz, n, chunk_sz),
            Mul#(chunk_sz, n, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}



\index{mkBRAMCore2@\te{mkBRAMCore2} (module)}
\index[function]{BRAM!mkBRAMCore2}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore2} &Dual port, single clock BRAM. \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore2#(Integer memSize,
                    Bool hasOutputRegister ) 
                   (BRAM_DUAL_PORT#(addr, data))
   provisos(Bits#(addr, addr_sz), Bits#(data, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}


\index{mkBRAMCore2BE@\te{mkBRAMCore2BE} (module)}
\index[function]{BRAM!mkBRAMCore2BE}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore2BE} &Byte-enabled, dual port BRAM. \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore2BE#(Integer memSize,
                      Bool hasOutputRegister
                     ) (BRAM_DUAL_PORT_BE#(addr, data, n))
   provisos(Bits#(addr, addr_sz),
            Bits#(data, data_sz),
            Div#(data_sz, n, chunk_sz),
            Mul#(chunk_sz, n, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}


\index{mkSyncBRAMCore2@\te{mkSyncBRAMCore2} (module)}
\index[function]{BRAM!mkSyncBRAMCore2}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkSyncBRAMCore2} &Dual port, dual clock BRAM. \\
\cline{2-2}
& \begin{libverbatim}
module mkSyncBRAMCore2#(Integer memSize,
                    Bool hasOutputRegister,
                    Clock clkA, Reset rstNA,
                    Clock clkB, Reset rstNB )
                    (BRAM_DUAL_PORT#(addr, data))
   provisos(Bits#(addr, addr_sz),Bits#(data, data_sz));
\end{libverbatim}
\\
\hline
\end{tabular}

\index{mkSyncBRAMCore2BE@\te{mkSyncBRAMCore2BE} (module)}
\index[function]{BRAM!mkSyncBRAMCore2BE}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkSyncBRAMCore2BE} &Dual port, dual clock byte-enabled BRAM. \\
\cline{2-2}
& \begin{libverbatim}
module mkSyncBRAMCore2BE#(Integer memSize,
                          Bool hasOutputRegister,
                          Clock clkA, Reset rstNA,
                          Clock clkB, Reset rstNB)
                       (BRAM_DUAL_PORT_BE#(addr, data, n))
   provisos(Bits#(addr, addr_sz),
            Bits#(data, data_sz),
            Div#(data_sz, n, chunk_sz),
            Mul#(chunk_sz, n, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}

\index{mkBRAMCore2Load@\te{mkBRAMCore2Load} (module)}
\index[function]{BRAM!mkBRAMCore2Load}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore2Load} &Dual port, single clock,  BRAM where the initial contents are
in \te{file}.  The parameter \te{binary} indicates whether the
contents of \te{file} are  binary (\te{True}) or hex (\te{False}).  \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore2Load#(Integer memSize,
                        Bool hasOutputRegister,
                        String file, Bool binary)
                       (BRAM_DUAL_PORT#(addr, data))
   provisos(Bits#(addr, addr_sz),Bits#(data, data_sz));
\end{libverbatim}
\\
\hline
\end{tabular}


\index{mkBRAMCore2BELoad@\te{mkBRAMCore2BELoad} (module)}
\index[function]{BRAM!mkBRAMCore2BELoad}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkBRAMCore2BELoad} &Dual port, single clock, byte-enabled  BRAM where the initial contents are
in \te{file}.  The parameter \te{binary} indicates whether the
contents of \te{file} are  binary (\te{True}) or hex (\te{False}).  \\
\cline{2-2}
& \begin{libverbatim}
module mkBRAMCore2BELoad#(Integer memSize,
                          Bool hasOutputRegister,
                          String file, Bool binary )
                    (BRAM_DUAL_PORT_BE#(addr, data, n))
   provisos(Bits#(addr, addr_sz),
            Bits#(data, data_sz),
            Div#(data_sz, n, chunk_sz),
            Mul#(chunk_sz, n, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}

\index{mkSyncBRAMCore2Load@\te{mkSyncBRAMCore2Load} (module)}
\index[function]{BRAM!mkSyncBRAMCore2Load}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkSyncBRAMCore2Load} & Dual port, dual clock BRAM with initial
contents in \te{file}.\\
\cline{2-2}
& \begin{libverbatim}
module mkSyncBRAMCore2Load#(Integer memSize,
                        Bool hasOutputRegister,
                        Clock clkA, Reset rstNA,
                        Clock clkB, Reset rstNB,
                        String file, Bool binary)
                        (BRAM_DUAL_PORT#(addr, data))
   provisos(Bits#(addr, addr_sz), Bits#(data, data_sz));
\end{libverbatim}
\\
\hline
\end{tabular}

\index{mkSyncBRAMCore2BELoad@\te{mkSyncBRAMCore2BELoad} (module)}
\index[function]{BRAM!mkSyncBRAMCore2BELoad}

\begin{tabular}{|p{1.4 in}|p{4.2 in}|}
\hline
& \\
\te{mkSyncBRAMCore2BELoad} & Dual port, dual clock, byte-enabledBRAM
with initial contents in \te{file}.\\
\cline{2-2}
& \begin{libverbatim}
module mkSyncBRAMCore2BELoad#(Integer memSize,
                              Bool hasOutputRegister,
                              Clock clkA, Reset rstNA,
                              Clock clkB, Reset rstNB,
                              String file, Bool binary)
                       (BRAM_DUAL_PORT_BE#(addr, data, n))
   provisos(Bits#(addr, addr_sz),
            Bits#(data, data_sz),
            Div#(data_sz, n, chunk_sz),
            Mul#(chunk_sz, n, data_sz) );
\end{libverbatim}
\\
\hline
\end{tabular}





{\bf Verilog Modules}

\te{BRAM} modules correspond to the following {\V}
modules, which are found in the Bluespec {\V} library, \te{\$BLUESPECDIR/Verilog/}.

\begin{center}
\begin{tabular} {|p{2.5 in}|p{2.5 in}|}
\hline
&\\
BSV Module Name & Verilog Module Names \\
&\\
\hline
\hline
\te{mkBRAMCore1}&\te{BRAM1.v}  \\
\hline
\te{mkBRAMCore1Load}&\te{BRAM1Load.v}\\
\hline
\te{mkBRAMCore1BE}&\te{BRAM1BE.v} \\
\hline
\te{mkBRAMCore1BELoad}&\te{BRAM1BELoad.v}  \\
\hline
\te{mkBRAMCore2}&\te{BRAM2.v}  \\
\te{mkSyncBRAMCore2}& \\
\hline
\te{mkBRAMCore2BE}&\te{BRAM2BE.v}\\
\te{mkSyncBRAMCore2BE}&\\
\hline
\te{mkBRAMCore2Load}&\te{BRAM2Load.v}  \\
\te{mkSyncBRAMCore2Load}& \\
\hline
\te{mkBRAMCore2BELoad}&\te{BRAM2BELoad.v}\\
\te{mkSyncBRAMCore2BELoad}&\\
\hline

\end{tabular}
\end{center}
