Commit b880afab authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

First beta version

parent c6003c76
......@@ -181,6 +181,13 @@ function vopenpin()
return s;
end
function vundefined()
local s={}
s.t="undefined";
return s;
end
-- constructor for a HDL signal
function signal(type, nbits, name, comment)
local t = {}
......@@ -192,13 +199,20 @@ function signal(type, nbits, name, comment)
end
-- constructor for a HDL port
function port(type, nbits, dir, name, comment)
function port(type, nbits, dir, name, comment, is_wb)
local t = {}
t.comment = comment;
t.comment = comment;
t.type = type;
t.range= nbits;
t.name = name;
t.dir = dir;
if(is_wb ~= nil and is_wb) then
t.is_wb = true;
else
t.is_wb = false;
end
return t;
end
......@@ -222,7 +236,7 @@ function cgen_build_clock_list()
remove_duplicates(allclocks);
for i,v in pairs(allclocks) do
table.insert(clockports, port(BIT, 0, "in", v));
table.insert(clockports, port(BIT, 0, "in", v, "", true));
end
return clockports;
......
This diff is collapsed.
......@@ -165,15 +165,18 @@ function cgen_generate_verilog_code(tree)
if(node.t ~= nil) then
if(node.t == "index") then
sig = cgen_find_sigport(node.name);
-- print("VI ", node.name, node.h, node.l);
ts.h=node.h;
ts.l=node.l;
ts.sig=sig;
ts.name=sig.name;
ts.type=sig.type;
if(ts.l ~= nil) then
ts.size = ts.h-ts.l+1;
else
ts.size = ts.h;
ts.size = 1;
end
return ts;
......@@ -182,7 +185,11 @@ function cgen_generate_verilog_code(tree)
ts.size = 0;
ts.value = node.val;
return ts;
else
elseif(node.t == "undefined") then
ts.type = UNDEFINED;
return ts;
else
ts.type = EXPRESSION;
ts.code = node;
return ts;
......@@ -238,11 +245,12 @@ function cgen_generate_verilog_code(tree)
tsd.sig.vlog_type = csel(inside_process, VLOG_REG, VLOG_WIRE);
emiti();
if (tss.type == OTHERS) then -- vhdl dst <= (others => x) expression
if (tss.type == OTHERS or tss.type == UNDEFINED) then -- vhdl dst <= (others => x) expression
local bin = string.format("%d'b", tsd.size);
local val = csel(tss.type == UNDEFINED, "X", csel(tss.value == 1, "1", "0"));
for i=1,tsd.size do
bin=bin..csel(tss.value == 1, "1", "0");
bin=bin..val;
end
emitx(csel(not inside_process, "assign ", "")..gen_subrange(tsd)..csel(inside_process," <= ", " = "));
......
......@@ -244,6 +244,7 @@ function cgen_generate_vhdl_code(tree)
local ts = {};
local sig;
-- print("tsize",node);
ts.node = node;
......@@ -256,22 +257,25 @@ function cgen_generate_vhdl_code(tree)
if(node.t ~= nil and node.t == "index") then
-- find the definition of the signal to determine its VHDL type.
sig = cgen_find_sigport(node.name);
sig = cgen_find_sigport(node.name);
-- and extract indexing bondaries (h downto l)
ts.h=node.h;
ts.l=node.l;
ts.name=sig.name;
ts.type=sig.type;
ts.h=node.h;
ts.l=node.l;
ts.name=sig.name;
ts.type=sig.type;
if(ts.l == nil) then
ts.size = 1;
ts.type = BIT;
else
ts.size = ts.h-ts.l+1;
end
if(ts.l == nil) then
ts.size = 1;
ts.type = BIT;
else
ts.size = ts.h-ts.l+1;
end
return ts;
return ts;
elseif(node.t ~= nil and node.t == "undefined") then
ts.type = UNDEFINED;
return ts;
-- if the subnode is not of "vi" type, treat is as an expression (arithmetic, logic, etc.)
else
......@@ -335,6 +339,8 @@ function cgen_generate_vhdl_code(tree)
if(tsd.type == tss.type) then
return(gen_subrange(tss));
elseif (tss.type == UNDEFINED) then
return "'X'"
-- dest: bit/slv/signed/unsigned <= src: numeric_constant;
elseif (tss.type == INTEGER) then
......@@ -368,7 +374,7 @@ function cgen_generate_vhdl_code(tree)
if(tsd.type == SIGNED) then
return("signed("..gen_subrange(tss)..")");
elseif (tsd.type == UNSIGNED) then
print(tss);
-- print(tss);
return("unsigned("..gen_subrange(tss)..")");
else die ("unsupported assignment: "..tsd.name.." "..tss.name); end
......
\relax
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{2}{section.1}}
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces An example of wbgen2-generated slave core}}{2}{figure.1}}
\newlabel{fig:slavecore}{{1}{2}{An example of wbgen2-generated slave core\relax }{figure.1}{}}
\@setckpt{intro}{
\setcounter{page}{3}
\setcounter{equation}{0}
\setcounter{enumi}{0}
\setcounter{enumii}{0}
\setcounter{enumiii}{0}
\setcounter{enumiv}{0}
\setcounter{footnote}{0}
\setcounter{mpfootnote}{0}
\setcounter{part}{0}
\setcounter{section}{1}
\setcounter{subsection}{0}
\setcounter{subsubsection}{0}
\setcounter{paragraph}{0}
\setcounter{subparagraph}{0}
\setcounter{figure}{1}
\setcounter{table}{0}
\setcounter{Item}{0}
\setcounter{Hfootnote}{0}
\setcounter{bookmark@seq@number}{0}
\setcounter{lstnumber}{1}
\setcounter{LT@tables}{0}
\setcounter{LT@chunks}{0}
\setcounter{subfigure}{0}
\setcounter{lofdepth}{1}
\setcounter{subtable}{0}
\setcounter{lotdepth}{1}
\setcounter{section@level}{1}
\setcounter{lstlisting}{0}
}
This diff is collapsed.
\section{Introduction}
\textbf{wbgen2} is a Lua script for generating VHDL Wishbone slave cores from a register set description provided by the user. By the ''slave core'' we mean a HDL entity which is connected to Wishbone bus on one side, and on the other side it provides ports for accessing memory mapped registers, FIFOs and RAMs, as shown on figure \ref{fig:slavecore}.
\InsertDefFig{slavecore.pdf}{An example of wbgen2-generated slave core}{fig:slavecore}{1}
The main features of wbgen2 are listed below:
\begin{itemize}
\item Generation of VHDL code for slaves consisting of memory mapped registers, FIFO registers and RAMs
\item Automatic minimal address space generation
\item Generation of C header files containing addresses consistent with the VHDL core
\item Customizable register types, with multiple access options and multiple clocking schemes
\item Support for most common VHDL types
\item (optional) automatic instantiation and wiring of slave core into the VHDL design
\item (optional) documentation generator.
\end{itemize}
\relax
\providecommand\BKM@entry[2]{}
\ifx\hyper@anchor\@undefined
\global \let \oldcontentsline\contentsline
\gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
\global \let \oldnewlabel\newlabel
\gdef \newlabel#1#2{\newlabelxx{#1}#2}
\gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
\AtEndDocument{\let \contentsline\oldcontentsline
\let \newlabel\oldnewlabel}
\else
\global \let \hyper@last\relax
\fi
\@input{title.aux}
\select@language{english}
\@writefile{toc}{\select@language{english}}
\@writefile{lof}{\select@language{english}}
\@writefile{lot}{\select@language{english}}
\select@language{english}
\@writefile{toc}{\select@language{english}}
\@writefile{lof}{\select@language{english}}
\@writefile{lot}{\select@language{english}}
\@input{intro.aux}
\BKM@entry{id=1,dest={73656374696F6E2E31}}{496E74726F64756374696F6E}
\@input{processing.aux}
\BKM@entry{id=2,dest={73656374696F6E2E32}}{776267656E3220736C617665206465736372697074696F6E2066696C6573}
\BKM@entry{id=3,dest={73756273656374696F6E2E322E31}}{536C617665206465736372697074696F6E2073796E746178}
\BKM@entry{id=4,dest={73756273656374696F6E2E322E32}}{436F6D6D6F6E2061747472696275746573}
\BKM@entry{id=5,dest={73756273656374696F6E2E322E33}}{5045524950484552414C20626C6F636B2061747472696275746573}
\BKM@entry{id=6,dest={73756273656374696F6E2E322E34}}{52454720626C6F636B2061747472696275746573}
\BKM@entry{id=7,dest={73756273656374696F6E2E322E35}}{4649454C4420626C6F636B}
\@input{regs.aux}
\BKM@entry{id=8,dest={73656374696F6E2E33}}{526567697374657273}
This diff is collapsed.
%!
/pdfmark where{pop}
{/globaldict where{pop globaldict}{userdict}ifelse/pdfmark/cleartomark load put}
ifelse
\documentclass[a4paper,11pt]{article}
\usepackage{lmodern}
\usepackage{t1enc}
\usepackage[pdftex]{hyperref}
\usepackage{listings}
\usepackage[pdftex]{color,graphicx}
\usepackage{bookmark}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage{relsize}
\usepackage{setspace}
\usepackage{xstring}
%\usepackage{tabularx}
\usepackage{ltablex}
%\usepackage{fancyhdr}
\usepackage{subfigure}
\usepackage{textcomp}
\usepackage{multirow}
\usepackage{fullpage}
%\pagestyle{fancy}
\widowpenalty=10000
\clubpenalty=10000
\brokenpenalty=10000
\sloppy
\lstset{
language=C++, % choose the language of the code
basicstyle=\tiny, % the size of the fonts that are used for the code
numbers=none, % where to put the line-numbers
%numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers
%stepnumber=1, % the step between two line-numbers
%numbersep=5pt, % how far the line-numbers are from the code
backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
showspaces=false, % show spaces adding particular underscores
showstringspaces=true, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
frame=tlBR, % adds a frame around the code
frameround=tttt, % a moze trBL / tttt
tabsize=2, % sets default tabsize to 2 spaces
captionpos=t, % sets the caption-position to top
breaklines=true, % sets automatic line breaking
breakatwhitespace=true, % sets if automatic breaks should only happen at whitespace
breakindent=100px,
prebreak=\ldots, % 1,
morekeywords={uint8_t,int32_t,int64_t,uint32_t,uint64_t},
%escapeinside={\%*}{*)} % if you want to add a comment within your code
lineskip=0pt,
inputencoding=utf8,
}
\newcommand{\HRule}{\rule{\linewidth}{0.3mm}}
\newcommand{\DocumentVersion}{20100223}
\def\us{\char`\_}
\newcommand{\InsertDefFig}[4]{
\begin{figure}[h]
\centering
\includegraphics[width=#4\textwidth]{#1}
\caption{#2}
\label{#3}
\end{figure}
}
\begin{document}
\selectlanguage{english}
\author{Tomasz Włostowski}
\title{wbgen2 documentation}
\include{title}
\include{intro}
\include{processing}
\include{regs}
\end{document}
\documentclass[a4paper,11pt]{article}
\usepackage{lmodern}
\usepackage{t1enc}
\usepackage[pdftex]{hyperref}
\usepackage{listings}
\usepackage[pdftex]{color,graphicx}
\usepackage{bookmark}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage{relsize}
\usepackage{setspace}
\usepackage{xstring}
%\usepackage{tabularx}
\usepackage{ltablex}
%\usepackage{fancyhdr}
\usepackage{subfigure}
\usepackage{textcomp}
\usepackage{multirow}
\usepackage{fullpage}
%\pagestyle{fancy}
\widowpenalty=10000
\clubpenalty=10000
\brokenpenalty=10000
\sloppy
\lstset{
language=C++, % choose the language of the code
basicstyle=\tiny, % the size of the fonts that are used for the code
numbers=none, % where to put the line-numbers
%numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers
%stepnumber=1, % the step between two line-numbers
%numbersep=5pt, % how far the line-numbers are from the code
backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
showspaces=false, % show spaces adding particular underscores
showstringspaces=true, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
frame=tlBR, % adds a frame around the code
frameround=tttt, % a moze trBL / tttt
tabsize=2, % sets default tabsize to 2 spaces
captionpos=t, % sets the caption-position to top
breaklines=true, % sets automatic line breaking
breakatwhitespace=true, % sets if automatic breaks should only happen at whitespace
breakindent=100px,
prebreak=\ldots, % 1,
morekeywords={uint8_t,int32_t,int64_t,uint32_t,uint64_t},
%escapeinside={\%*}{*)} % if you want to add a comment within your code
lineskip=0pt,
inputencoding=utf8,
}
\newcommand{\HRule}{\rule{\linewidth}{0.3mm}}
\newcommand{\DocumentVersion}{20100223}
\def\us{\char`\_}
\newcommand{\InsertDefFig}[4]{
\begin{figure}[h]
\centering
\includegraphics[width=#4\textwidth]{#1}
\caption{#2}
\label{#3}
\end{figure}
}
\begin{document}
\selectlanguage{english}
\author{Tomasz Włostowski}
\title{wbgen2 documentation}
\include{title}
\include{intro}
\include{processing}
\end{document}
\relax
\@writefile{toc}{\contentsline {section}{\numberline {2}wbgen2 slave description files}{3}{section.2}}
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Structure of slave cores generated by wbgen2}}{3}{figure.2}}
\newlabel{fig:reglayout}{{2}{3}{Structure of slave cores generated by wbgen2\relax }{figure.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Slave description syntax}{3}{subsection.2.1}}
\gdef \LT@i {\LT@entry
{1}{98.15825pt}\LT@entry
{1}{354.80965pt}}
\gdef \LT@ii {\LT@entry
{1}{98.15825pt}\LT@entry
{1}{298.13481pt}}
\gdef \LT@iii {\LT@entry
{1}{98.15825pt}\LT@entry
{1}{354.80965pt}}
\gdef \LT@iv {\LT@entry
{1}{105.342pt}\LT@entry
{1}{278.1937pt}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Common attributes}{4}{subsection.2.2}}
\@writefile{lot}{\contentsline {table}{\numberline {1}{Attributes common for all description blocks}}{4}{table.1}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}PERIPHERAL block attributes}{4}{subsection.2.3}}
\@writefile{lot}{\contentsline {table}{\numberline {2}{Attributes specific for \textbf {peripheral} blocks}}{4}{table.2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}REG block attributes}{4}{subsection.2.4}}
\@writefile{lot}{\contentsline {table}{\numberline {3}{Attributes specific for \textbf {reg} blocks}}{4}{table.3}}
\gdef \LT@v {\LT@entry
{1}{126.61101pt}\LT@entry
{1}{326.35689pt}}
\@writefile{lot}{\contentsline {table}{\numberline {4}{Possible field types for \textbf {reg} blocks}}{5}{table.4}}
\newlabel{table:fieldtypes}{{4}{5}{Possible field types for \textbf {reg} blocks\relax }{table.4}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Register alignment}}{5}{figure.3}}
\newlabel{fig:regalignment}{{3}{5}{Register alignment\relax }{figure.3}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.5}FIELD block}{5}{subsection.2.5}}
\@writefile{lot}{\contentsline {table}{\numberline {5}{Attributes specific for \textbf {field} blocks}}{6}{table.5}}
\@setckpt{processing}{
\setcounter{page}{7}
\setcounter{equation}{0}
\setcounter{enumi}{0}
\setcounter{enumii}{0}
\setcounter{enumiii}{0}
\setcounter{enumiv}{0}
\setcounter{footnote}{0}
\setcounter{mpfootnote}{0}
\setcounter{part}{0}
\setcounter{section}{2}
\setcounter{subsection}{5}
\setcounter{subsubsection}{0}
\setcounter{paragraph}{0}
\setcounter{subparagraph}{0}
\setcounter{figure}{3}
\setcounter{table}{5}
\setcounter{Item}{0}
\setcounter{Hfootnote}{0}
\setcounter{bookmark@seq@number}{0}
\setcounter{lstnumber}{29}
\setcounter{LT@tables}{5}
\setcounter{LT@chunks}{1}
\setcounter{subfigure}{0}
\setcounter{lofdepth}{1}
\setcounter{subtable}{0}
\setcounter{lotdepth}{1}
\setcounter{section@level}{2}
\setcounter{lstlisting}{0}
}
This diff is collapsed.
\section{wbgen2 slave description files}
In order to generate the slave core, user must provide a slave description file, which tells wbgen2 what he wants to have inside the core. Each slave description file contains a tree-like structure, describing the peripheral's register layout for a single Wishbone peripheral.
Slaves may contain registers, FIFO registers and RAM memories. Registers and FIFO registers consist of fields (see figure \ref{fig:reglayout}), RAMs are accessible as plain, synchronous memories.
\InsertDefFig{reglayout.pdf}{Structure of slave cores generated by wbgen2}{fig:reglayout}{0.8}
\subsection{Slave description syntax}
Slave description files have C-like syntax. Each file may contain the description of a single slave core. The description must begin with \textit{peripheral} block, which contains one or more of
\textit{reg}, \textit{fiforeg} or \textit{ram} subblocks. Each \textit{reg} and \textit{fiforeg} subblock must contain at least one \textit{field}. Inside each block, there is a list of attributes. The listing below shows a dummy description file layout:
\begin{lstlisting}
peripheral {
name = "My peripheral";
c_prefix = "periph1";
hdl_prefix = "periph1";
reg {
name = "My register";
prefix = "myreg";
description = "A longer description";
field {
name = "My field 1";
prefix = "field1";
type = type-of-the-field; // BIT, SLV, etc...
};
-- more fields here...
};
fiforeg {
name = "My FIFO register";
prefix = "myram";
field { ... };
};
ram {
name = "My RAM";
prefix = "myram";
size = 1024;
};
};
\end{lstlisting}
\subsection{Common attributes}
There are few attributes, which are common for all types of blocks in the description file:
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{name}
\newline
(mandatory)
& contains a short (single line) human-readable name for the peripheral/register/field. This name is not used directly in code generation (except for the code comments).
\\\hline
\textbf{c\us prefix}\newline
\textbf{hdl\us prefix}\newline
\textbf{prefix}\newline
(mandatory)
& contains a short prefix for each block which is used for generation of VHDL port/signal names and C macros. Names are generated by concatenating the prefixes. In the example shown above, the signal name of field "My field 1" would be \textit{periph1\us myreg\us field1}. The format of \textbf{prefix} value must follow the language syntax rules and your coding style. Note that you can provide either separate prefixes for C/HDL languages (\textbf{c\us prefix, hdl\us prefix}) or a single \textbf{prefix} for both.
\\\hline
\textbf{description}\newline
(optional)
& a longer description of the block, used by the documentation generator.
\\\hline
\caption{Attributes common for all description blocks}
\end{tabularx}
%\end{table}
\subsection{PERIPHERAL block attributes}
\textbf{Peripheral} block is the top-level block in the description file.
\newline
Block-specific attributes:
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{hdl\us entity}
\newline
(mandatory)
& name of the VHDL entity of the slave core to be generated.
\\\hline
\caption{Attributes specific for \textbf{peripheral} blocks}
\end{tabularx}
%\end{table}
\subsection{REG block attributes}
\textbf{Reg} block describes a single memory-mapped register. Each \textbf{reg} block must contain one or more
\textbf{field} blocks. Available field types are listed in table \ref{table:fieldtypes}.
\newline Block-specific attributes:
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{align = val}
\newline
(optional)
& Alignment value for the field address. When given, wbgen2 will align the address of this register to the nearest multiple of \textit{val}. See also figure \ref{fig:regalignment}.
\\\hline
\caption{Attributes specific for \textbf{reg} blocks}
\end{tabularx}
%\end{table}
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|l|X|}
\hline
\textbf{Type} & \textbf{Description}
\\\hline
BIT & VHDL single bit of type \texttt{std\us logic} \\
SLV & VHDL field of type \texttt{std\us logic\us vector} \\
SIGNED & VHDL field of type \texttt{signed} \\
UNSIGNED & VHDL field of type \texttt{unsigned} \\
MONOSTABLE & VHDL field of type \texttt{std\us logic}, generating a single-cycle positive pulse upon bus write of '1'. \\
PASS\us THROUGH & special field, for which wbgen2 will generate only the address decoding logic which provides "wr" signal asserted high for a single WB clock cycle upon each write to the register. The written value will be fed to the corresponding SLV output directly from the Wishbone bus (just wires, no registers in between).
\\\hline
\caption{Possible field types for \textbf{reg} blocks}
\label{table:fieldtypes}
\end{tabularx}
%\end{table}
\InsertDefFig{alignment.pdf}{Register alignment}{fig:regalignment}{0.4}
\subsection{FIELD block}
\textbf{Field} block describes a single register field. There are several types of fields, shown in table \ref{table:fieldtypes}. It's the most elementary block in the design.
\newline
Block-specific attributes:
%\begin{table}[]
\begin{tabularx}{\textwidth}{|p{4cm}|X|}
\hline
\textbf{type}\newline (mandatory)
& type of the field. See table \ref {table:fieldtypes} \\\hline
\textbf{size}\newline (mandatory for: SLV, optional for SIGNED, UNSIGNED)
& size of the field in bits. For SIGNED and UNSIGNED types it's interchangeable with \textbf {range} attribute.\\\hline
\textbf{range = \{min,max\}}\newline (optional for SIGNED, UNSIGNED)
& minimal and maximal field value. When provided, wbgen2 will automatically calculate the necessary number of bits. \\\hline
\textbf{access\us bus}\newline
\textbf{access\us dev}\newline
(optional)
& field access flags. \textbf{access\us bus} defines how the field can be accessed from the Wishbone bus, \textbf{access\us dev} defines how the field can be modified by the HDL entity in which the slave core is instantiated. Access flags can have one of these values: READ\us ONLY, WRITE\us ONLY, READ\us WRITE. For the possible access combinations refer to table \ref{table:accessflags}. \newline
The default value is READ\us WRITE (from the bus) and READ\us ONLY (from the device).
\\\hline
\textbf{access}\newline
(optional)
& can be used instead of \textbf{access\us bus} and \textbf{access\us dev} to define access rights. See table \ref{table:accessflags}.
\\\hline
\textbf{align = num}\newline
(optional)
& when given, the bit offset at which field will be allocated, will be aligned to integer multiple of \textbf{num}. Default value is 1 (no alignment).
\\\hline
\textbf{clock}\newline
(optional)
& can be used to provide a clock port name if the field needs to operate in clock domain other than Wishbone bus clock. wbgen2 will automatically provide the necessary synchronization logic. Clock names are automatically appended to slave core entity port list. If no \textbf{clock} attribute is provided, wbgen2 defaults to Wishbone bus clock.
\\\hline
\textbf{load}\newline
(optional for RW/RW fields)
& this attribute is applicable only to RW/RW-accessed fields (e.g. the fields which are writable both from the bus and the device). There are two possible values, indicating where the field register will be physically placed (see figure \ref{fig:loadintext}):
\newline
\textit{LOAD\us EXT} - the field register is placed outside the slave core. Upon bus write operation, slave outputs the new value to the output port and asserts the "load" signal for a single clock cycle. The device has to handle these signals and update the value of the register respectively.
\newline
\textit{LOAD\us INT} - the field register is placed inside the slave core. When the device wants to update it's value, it passes it to certain input port and asserts the load signal high. \textit{not implemented yet}.
\\\hline
\caption{Attributes specific for \textbf{field} blocks}
\end{tabularx}
%\end{table}
\section{wbgen2 slave description files}
In order to generate the slave core, user must provide a slave description file, which tells wbgen2 what he wants to have inside the core. Each slave description file contains a tree-like structure, describing the peripheral's register layout for a single Wishbone peripheral.
Slaves may contain registers, FIFO registers and RAM memories. Registers and FIFO registers consist of fields (see figure \ref{fig:reglayout}), RAMs are accessible as plain, synchronous memories.
\InsertDefFig{reglayout.pdf}{Structure of slave cores generated by wbgen2}{fig:reglayout}{0.8}
\subsection{Slave description syntax}
Slave description files have C-like syntax. Each file may contain the description of a single slave core. The description must begin with \textit{peripheral} block, which contains one or more of
\textit{reg}, \textit{fiforeg} or \textit{ram} subblocks. Each \textit{reg} and \textit{fiforeg} subblock must contain at least one \textit{field}. Inside each block, there is a list of attributes. The listing below shows a dummy description file layout:
\begin{lstlisting}
peripheral {
name = "My peripheral";
c_prefix = "periph1";
hdl_prefix = "periph1";
reg {
name = "My register";
prefix = "myreg";
description = "A longer description";
field {
name = "My field 1";
prefix = "field1";
type = type-of-the-field; // BIT, SLV, etc...
};
-- more fields here...
};
fiforeg {
name = "My FIFO register";
prefix = "myram";
field { ... };
};
ram {
name = "My RAM";
prefix = "myram";
size = 1024;
};
};
\end{lstlisting}
\subsection{Common attributes}
There are few attributes, which are common for all types of blocks in the description file:
\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{name}
\newline
(mandatory)
& contains a short (single line) human-readable name for the peripheral/register/field. This name is not used directly in code generation (except for the code comments).
\\\hline
\textbf{c\us prefix}\newline
\textbf{hdl\us prefix}\newline
\textbf{prefix}\newline
(mandatory)
& contains a short prefix for each block which is used for generation of VHDL port/signal names and C macros. Names are generated by concatenating the prefixes. In the example shown above, the signal name of field "My field 1" would be \textit{periph1\us myreg\us field1}. The format of \textbf{prefix} value must follow the language syntax rules and your coding style. Note that you can provide either separate prefixes for C/HDL languages (\textbf{c\us prefix, hdl\us prefix}) or a single \textbf{prefix} for both.
\\\hline
\textbf{description}\newline
(optional)
& a longer description of the block, used by the documentation generator.
\\\hline
\end{tabularx}
\end{table}
\subsection{PERIPHERAL block attributes}
\textbf{Peripheral} block is the top-level block in the description file.
\newline
Block-specific attributes:
\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{hdl\us entity}
\newline
(mandatory)
& name of the VHDL entity of the slave core to be generated.
\\\hline
\end{tabularx}
\end{table}
\subsection{REG block attributes}
\textbf{Reg} block describes a single memory-mapped register. Each \textbf{reg} block must contain one or more
\textbf{field} blocks. Available field types are listed in table \ref{table:fieldtypes}.
\newline Block-specific attributes:
\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{align = val}
\newline
(optional)
& Alignment value for the field address. When given, wbgen2 will align the address of this register to the nearest multiple of \textit{val}. See also figure \ref{fig:regalignment}.
\\\hline
\end{tabularx}
\end{table}
\begin{table}[h]
\begin{tabularx}{\textwidth}{|l|X|}
\hline
\textbf{Type} & \textbf{Description}
\\\hline
BIT & VHDL single bit of type \texttt{std\us logic} \\
SLV & VHDL field of type \texttt{std\us logic\us vector} \\
SIGNED & VHDL field of type \texttt{signed} \\
UNSIGNED & VHDL field of type \texttt{unsigned} \\
MONOSTABLE & VHDL field of type \texttt{std\us logic}, generating a single-cycle positive pulse upon bus write of '1'. \\
PASS\us THROUGH & special field, for which wbgen2 will generate only the address decoding logic which provides "wr" signal asserted high for a single WB clock cycle upon each write to the register. The written value will be fed to the corresponding SLV output directly from the Wishbone bus (just wires, no registers in between).
\\\hline
\end{tabularx}
\label{table:fieldtypes}
\caption{Possible field types for \textbf{reg} blocks}
\end{table}
\InsertDefFig{alignment.pdf}{Register alignment}{fig:regalignment}{0.4}
\subsection{FIELD block}
\textbf{Field} block describes a single register field. There are several types of fields, shown in table \ref{table:fieldtypes}. It's the most elementary block in the design.
\newline
Block-specific attributes:
\begin{table}[]
\begin{tabularx}{\textwidth}{|p{4cm}|X|}
\hline
\textbf{type}\newline (mandatory)
& type of the field. See table \ref {table:fieldtypes} \\\hline
\textbf{size}\newline (mandatory for: SLV, optional for SIGNED, UNSIGNED)
& size of the field in bits. For SIGNED and UNSIGNED types it's interchangeable with \textbf {range} attribute.\\\hline
\textbf{range = \{min,max\}}\newline (optional for SIGNED, UNSIGNED)
& minimal and maximal field value. When provided, wbgen2 will automatically calculate the necessary number of bits. \\\hline
\textbf{access\us bus}\newline
\textbf{access\us dev}\newline
(optional)
& field access flags. \textbf{access\us bus} defines how the field can be accessed from the Wishbone bus, \textbf{access\us dev} defines how the field can be modified by the HDL entity in which the slave core is instantiated. Access flags can have one of these values: READ\us ONLY, WRITE\us ONLY, READ\us WRITE. For the possible access combinations refer to table \ref{table:accessflags}. \newline
The default value is READ\us WRITE (from the bus) and READ\us ONLY (from the device).
\\\hline
\textbf{access}\newline
(optional)
& can be used instead of \textbf{access\us bus} and \textbf{access\us dev} to define access rights. See table \ref{table:accessflags}.
\\\hline
\textbf{align = num}\newline
(optional)
& when given, the bit offset at which field will be allocated, will be aligned to integer multiple of \textbf{num}. Default value is 1 (no alignment).
\\\hline
\textbf{clock}\newline
(optional)
& can be used to provide a clock port name if the field needs to operate in clock domain other than Wishbone bus clock. wbgen2 will automatically provide the necessary synchronization logic. Clock names are automatically appended to slave core entity port list. If no \textbf{clock} attribute is provided, wbgen2 defaults to Wishbone bus clock.
\\\hline
\textbf{load}\newline
(optional for RW/RW fields)
& this attribute is applicable only to RW/RW-accessed fields (e.g. the fields which are writable both from the bus and the device). There are two possible values, indicating where the field register will be physically placed (see figure \ref{fig:loadintext}):
\newline
\textit{LOAD\us EXT} - the field register is placed outside the slave core. Upon bus write operation, slave outputs the new value to the output port and asserts the "load" signal for a single clock cycle. The device has to handle these signals and update the value of the register respectively.
\newline
\textit{LOAD\us INT} - the field register is placed inside the slave core. When the device wants to update it's value, it passes it to certain input port and asserts the load signal high. \textit{not implemented yet}.
\\\hline
\end{tabularx}
\end{table}
\section{wbgen2 slave description files}
In order to generate the slave core, user must provide a slave description file, which tells wbgen2 what he wants to have inside the core. Each slave description file contains a tree-like structure, describing the peripheral's register layout for a single Wishbone peripheral.
Slaves may contain registers, FIFO registers and RAM memories. Registers and FIFO registers consist of fields (see figure \ref{fig:reglayout}), RAMs are accessible as plain, synchronous memories.
\InsertDefFig{reglayout.pdf}{Structure of slave cores generated by wbgen2}{fig:reglayout}{0.8}
\subsection{Slave description syntax}
Slave description files have C-like syntax. Each file may contain the description of a single slave core. The description must begin with \textit{peripheral} block, which contains one or more of
\textit{reg}, \textit{fiforeg} or \textit{ram} subblocks. Each \textit{reg} and \textit{fiforeg} subblock must contain at least one \textit{field}. Inside each block, there is a list of attributes. The listing below shows a dummy description file layout:
\begin{lstlisting}
peripheral {
name = "My peripheral";
c_prefix = "periph1";
hdl_prefix = "periph1";
reg {
name = "My register";
prefix = "myreg";
description = "A longer description";
field {
name = "My field 1";
prefix = "field1";
type = type-of-the-field; // BIT, SLV, etc...
};
-- more fields here...
};
fiforeg {
name = "My FIFO register";
prefix = "myram";
field { ... };
};
ram {
name = "My RAM";
prefix = "myram";
size = 1024;
};
};
\end{lstlisting}
\subsection{Common attributes}
There are few attributes, which are common for all types of blocks in the description file:
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{name}
\newline
(mandatory)
& contains a short (single line) human-readable name for the peripheral/register/field. This name is not used directly in code generation (except for the code comments).
\\\hline
\textbf{c\us prefix}\newline
\textbf{hdl\us prefix}\newline
\textbf{prefix}\newline
(mandatory)
& contains a short prefix for each block which is used for generation of VHDL port/signal names and C macros. Names are generated by concatenating the prefixes. In the example shown above, the signal name of field "My field 1" would be \textit{periph1\us myreg\us field1}. The format of \textbf{prefix} value must follow the language syntax rules and your coding style. Note that you can provide either separate prefixes for C/HDL languages (\textbf{c\us prefix, hdl\us prefix}) or a single \textbf{prefix} for both.
\\\hline
\textbf{description}\newline
(optional)
& a longer description of the block, used by the documentation generator.
\\\hline
\caption{Attributes common for all description blocks}
\end{tabularx}
%\end{table}
\subsection{PERIPHERAL block attributes}
\textbf{Peripheral} block is the top-level block in the description file.
\newline
Block-specific attributes:
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{hdl\us entity}
\newline
(mandatory)
& name of the VHDL entity of the slave core to be generated.
\\\hline
\caption{Attributes specific for \textbf{peripheral} blocks}
\end{tabularx}
%\end{table}
\subsection{REG block attributes}
\textbf{Reg} block describes a single memory-mapped register. Each \textbf{reg} block must contain one or more
\textbf{field} blocks. Available field types are listed in table \ref{table:fieldtypes}.
\newline Block-specific attributes:
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|p{3cm}|X|}
\hline
\textbf{align = val}
\newline
(optional)
& Alignment value for the field address. When given, wbgen2 will align the address of this register to the nearest multiple of \textit{val}. See also figure \ref{fig:regalignment}.
\\\hline
\caption{Attributes specific for \textbf{reg} blocks}
\end{tabularx}
%\end{table}
%\begin{table}[h]
\begin{tabularx}{\textwidth}{|l|X|}
\hline
\textbf{Type} & \textbf{Description}
\\\hline
BIT & VHDL single bit of type \texttt{std\us logic} \\
SLV & VHDL field of type \texttt{std\us logic\us vector} \\
SIGNED & VHDL field of type \texttt{signed} \\
UNSIGNED & VHDL field of type \texttt{unsigned} \\
MONOSTABLE & VHDL field of type \texttt{std\us logic}, generating a single-cycle positive pulse upon bus write of '1'. \\
PASS\us THROUGH & special field, for which wbgen2 will generate only the address decoding logic which provides "wr" signal asserted high for a single WB clock cycle upon each write to the register. The written value will be fed to the corresponding SLV output directly from the Wishbone bus (just wires, no registers in between).
\\\hline
\caption{Possible field types for \textbf{reg} blocks}
\label{table:fieldtypes}
\end{tabularx}
%\end{table}
\InsertDefFig{alignment.pdf}{Register alignment}{fig:regalignment}{0.4}
\subsection{FIELD block}
\textbf{Field} block describes a single register field. There are several types of fields, shown in table \ref{table:fieldtypes}. It's the most elementary block in the design.
\newline
Block-specific attributes:
%\begin{table}[]
\begin{tabularx}{\textwidth}{|p{4cm}|X|}
\hline
\textbf{type}\newline (mandatory)
& type of the field. See table \ref {table:fieldtypes} \\\hline
\textbf{size}\newline (mandatory for: SLV, optional for SIGNED, UNSIGNED)
& size of the field in bits. For SIGNED and UNSIGNED types it's interchangeable with \textbf {range} attribute.\\\hline
\textbf{range = \{min,max\}}\newline (optional for SIGNED, UNSIGNED)
& minimal and maximal field value. When provided, wbgen2 will automatically calculate the necessary number of bits. \\\hline
\textbf{access\us bus}\newline
\textbf{access\us dev}\newline
(optional)
& field access flags. \textbf{access\us bus} defines how the field can be accessed from the Wishbone bus, \textbf{access\us dev} defines how the field can be modified by the HDL entity in which the slave core is instantiated. Access flags can have one of these values: READ\us ONLY, WRITE\us ONLY, READ\us WRITE. For the possible access combinations refer to table \ref{table:accessflags}. \newline
The default value is READ\us WRITE (from the bus) and READ\us ONLY (from the device).
\\\hline
\textbf{access}\newline
(optional)
& can be used instead of \textbf{access\us bus} and \textbf{access\us dev} to define access rights. See table \ref{table:accessflags}.
\\\hline
\textbf{align = num}\newline
(optional)
& when given, the bit offset at which field will be allocated, will be aligned to integer multiple of \textbf{num}. Default value is 1 (no alignment).
\\\hline
\textbf{clock}\newline
(optional)
& can be used to provide a clock port name if the field needs to operate in clock domain other than Wishbone bus clock. wbgen2 will automatically provide the necessary synchronization logic. Clock names are automatically appended to slave core entity port list. If no \textbf{clock} attribute is provided, wbgen2 defaults to Wishbone bus clock.
\\\hline
\textbf{load}\newline
(optional for RW/RW fields)
& this attribute is applicable only to RW/RW-accessed fields (e.g. the fields which are writable both from the bus and the device). There are two possible values, indicating where the field register will be physically placed (see figure \ref{fig:loadintext}):
\newline
\textit{LOAD\us EXT} - the field register is placed outside the slave core. Upon bus write operation, slave outputs the new value to the output port and asserts the "load" signal for a single clock cycle. The device has to handle these signals and update the value of the register respectively.
\newline
\textit{LOAD\us INT} - the field register is placed inside the slave core. When the device wants to update it's value, it passes it to certain input port and asserts the load signal high. \textit{not implemented yet}.
\\\hline
%\caption{Attributes specific for \textbf{field} blocks}
\end{tabularx}
$\end{table}
\relax
\@writefile{toc}{\contentsline {section}{\numberline {3}Registers}{7}{section.3}}
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces wbgen2 register type cheatsheet - standard registers}}{7}{figure.4}}
\newlabel{fig:cheatsheet}{{4}{7}{wbgen2 register type cheatsheet - standard registers\relax }{figure.4}{}}
\@setckpt{regs}{
\setcounter{page}{8}
\setcounter{equation}{0}
\setcounter{enumi}{0}
\setcounter{enumii}{0}
\setcounter{enumiii}{0}
\setcounter{enumiv}{0}
\setcounter{footnote}{0}
\setcounter{mpfootnote}{0}
\setcounter{part}{0}
\setcounter{section}{3}
\setcounter{subsection}{0}
\setcounter{subsubsection}{0}
\setcounter{paragraph}{0}
\setcounter{subparagraph}{0}
\setcounter{figure}{4}
\setcounter{table}{5}
\setcounter{Item}{0}
\setcounter{Hfootnote}{0}
\setcounter{bookmark@seq@number}{0}
\setcounter{lstnumber}{29}
\setcounter{LT@tables}{5}
\setcounter{LT@chunks}{1}
\setcounter{subfigure}{0}
\setcounter{lofdepth}{1}
\setcounter{subtable}{0}
\setcounter{lotdepth}{1}
\setcounter{section@level}{1}
\setcounter{lstlisting}{0}
}
\section{Registers}
wbgen2 supports various types of memory mapped I/O registers and fields:
\begin{itemize}
\item SLV, SIGNED, UNSIGNED and BIT standard registers
\item Bus-synchronous (operating with the same clock as the WB bus) or asynchronous (using externally supplied clock). wbgen2 automatically provides all necessary synchronization logic.
\item MONOSTABLE registers which generate positive pulse upon write of '1'.
'\item PASS\us THROUGH registers
\item Different access configurations
\item Single register can contain fields of different types, clocks and access.
\end{itemize}
Figures \ref{fig:cheatsheet} and \ref{fig:cheatsheetspecial} show all possible register field types.
\InsertDefFig{cheatsheet.pdf}{wbgen2 register type cheatsheet - standard registers}{fig:cheatsheet}{1}
\ No newline at end of file
\section{Registers}
wbgen2 supports various types of memory mapped I/O registers and fields:
\begin{itemize}
\item SLV, SIGNED, UNSIGNED and BIT standard registers
\item Bus-synchronous (operating with the same clock as the WB bus) or asynchronous (using externally supplied clock). wbgen2 automatically provides all necessary synchronization logic.
\item MONOSTABLE registers which generate positive pulse upon write of '1'.
'\item PASS\us THROUGH registers
\item Different access configurations
\item Single register can contain fields of different types, clocks and access.
\end{itemize}
Figure \ref{fig:cheatsheet} is a cheatsheet, containing all possible register field types.
\ No newline at end of file
\relax
\@setckpt{title}{
\setcounter{page}{2}
\setcounter{equation}{0}
\setcounter{enumi}{0}
\setcounter{enumii}{0}
\setcounter{enumiii}{0}
\setcounter{enumiv}{0}
\setcounter{footnote}{0}
\setcounter{mpfootnote}{0}
\setcounter{part}{0}
\setcounter{section}{0}
\setcounter{subsection}{0}
\setcounter{subsubsection}{0}
\setcounter{paragraph}{0}
\setcounter{subparagraph}{0}
\setcounter{figure}{0}
\setcounter{table}{0}
\setcounter{Item}{0}
\setcounter{Hfootnote}{0}
\setcounter{bookmark@seq@number}{0}
\setcounter{lstnumber}{1}
\setcounter{LT@tables}{0}
\setcounter{LT@chunks}{0}
\setcounter{subfigure}{0}
\setcounter{lofdepth}{1}
\setcounter{subtable}{0}
\setcounter{lotdepth}{1}
\setcounter{section@level}{0}
\setcounter{lstlisting}{0}
}
This diff is collapsed.
\begin{center}
\textsc{European Organization for Nuclear Research}
\\
\textsc{Organisation Europeenne pour la Recherche Nucleaire}
\HRule \\[4cm]
%\includegraphics[width=0.30\textwidth]{./drawings/wr_logo.png}
{\huge \bfseries wbgen2}
\\[1cm]
{\LARGE A simple Wishbone slave core generator}
\\[0.2cm]
{\large Version: \bfseries\DocumentVersion}
\\[8cm]
\end{center}
\begin{minipage}{0.4\textwidth}
\begin{flushleft} \small
Tomasz \textsc{Włostowski}\\
CERN BE-Co-HT\\
\end{flushleft}
\end{minipage}
\begin{center}
\vfill
\HRule\\
\end{center}
[General]
def_graphic_ext=eps
img_extIsRegExp=false
img_extensions=.eps .jpg .jpeg .png .pdf .ps .fig .gif
kileprversion=2
kileversion=2.0.84
lastDocument=regs.tex
masterDocument=
name=wbgen2_doc
pkg_extIsRegExp=false
pkg_extensions=.cls .sty .bbx .cbx .lbx
src_extIsRegExp=false
src_extensions=.tex .ltx .latex .dtx .ins
[Tools]
MakeIndex=
QuickBuild=
[item:intro.tex]
archive=true
column=1
encoding=
highlight=
line=0
mode=
open=false
order=-1
[item:main.tex]
archive=true
column=0
encoding=UTF-8
highlight=LaTeX
line=76
mode=LaTeX
open=true
order=0
[item:processing.tex]
archive=true
column=0
encoding=UTF-8
highlight=LaTeX
line=6
mode=LaTeX
open=true
order=1
[item:regs.tex]
archive=true
column=101
encoding=UTF-8
highlight=LaTeX
line=12
mode=LaTeX
open=true
order=2
[item:title.tex]
archive=true
column=167092456
encoding=
highlight=
line=0
mode=
open=false
order=-1
[item:wbgen2_doc.kilepr]
archive=true
column=7209065
encoding=
highlight=
line=0
mode=
open=false
order=-1
[view-settings,view=0,item:main.tex]
CursorColumn=0
CursorLine=76
[view-settings,view=0,item:processing.tex]
CursorColumn=0
CursorLine=6
[view-settings,view=0,item:regs.tex]
CursorColumn=101
CursorLine=12
......@@ -773,10 +773,10 @@ Project_Version = 6
Project_DefaultLib = work
Project_SortMethod = unused
Project_Files_Count = 2
Project_File_0 = /home/slayer/wbgen2_svn/wbgen2/examples/RAMs/output/wb_slave_test_rams.vhdl
Project_File_P_0 = vhdl_novitalcheck 0 file_type vhdl group_id 0 vhdl_nodebug 0 vhdl_1164 1 vhdl_noload 0 vhdl_synth 0 vhdl_enable0In 0 folder {Top Level} last_compile 0 vhdl_disableopt 0 vhdl_vital 0 vhdl_vopt 1 vhdl_warn1 1 vhdl_explicit 1 vhdl_warn2 1 vhdl_showsource 0 vhdl_warn3 1 vhdl_0InOptions {} vhdl_warn4 1 vhdl_options {} vhdl_warn5 1 ood 1 compile_to work compile_order 1 cover_nosub 0 dont_compile 0 vhdl_use93 2002
Project_File_1 = /home/slayer/wbgen2_svn/wbgen2/examples/RAMs/testbench.v
Project_File_P_1 = cover_toggle 0 vlog_protect 0 file_type verilog group_id 0 cover_exttoggle 0 cover_cond 0 vlog_nodebug 0 vlog_1995compat 0 cover_branch 0 vlog_noload 0 folder {Top Level} last_compile 0 cover_fsm 0 vlog_enable0In 0 vlog_disableopt 0 vlog_vopt 1 vlog_hazard 0 vlog_showsource 0 ood 1 vlog_0InOptions {} vlog_options {} compile_to work vlog_upper 0 compile_order 0 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_0 = /home/slayer/wbgen2_svn/wbgen2/examples/RAMs/testbench.v
Project_File_P_0 = cover_toggle 0 vlog_protect 0 file_type verilog group_id 0 cover_exttoggle 0 cover_cond 0 vlog_nodebug 0 vlog_1995compat 0 cover_branch 0 vlog_noload 0 folder {Top Level} last_compile 0 cover_fsm 0 vlog_enable0In 0 vlog_disableopt 0 vlog_vopt 1 vlog_hazard 0 vlog_showsource 0 ood 1 vlog_0InOptions {} vlog_options {} compile_to work vlog_upper 0 compile_order 0 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_1 = /home/slayer/wbgen2_svn/wbgen2/examples/RAMs/output/wb_slave_test_rams.vhdl
Project_File_P_1 = vhdl_novitalcheck 0 file_type vhdl group_id 0 vhdl_nodebug 0 vhdl_1164 1 vhdl_noload 0 vhdl_synth 0 vhdl_enable0In 0 folder {Top Level} last_compile 0 vhdl_disableopt 0 vhdl_vital 0 vhdl_vopt 1 vhdl_warn1 1 vhdl_explicit 1 vhdl_warn2 1 vhdl_showsource 0 vhdl_warn3 1 vhdl_0InOptions {} vhdl_warn4 1 vhdl_options {} vhdl_warn5 1 ood 1 compile_to work compile_order 1 cover_nosub 0 dont_compile 0 vhdl_use93 2002
Project_Sim_Count = 0
Project_Folder_Count = 0
Echo_Compile_Output = 0
......@@ -806,6 +806,6 @@ XML_DoubleClick = Edit
XML_CustomDoubleClick =
LOGFILE_DoubleClick = Edit
LOGFILE_CustomDoubleClick =
EditorState = {tabbed horizontal 1} {/home/slayer/wbgen2_svn/wbgen2/examples/RAMs/wishbone_stuff.v 0 0} {/home/slayer/wbgen2_svn/wbgen2/examples/RAMs/run.do 0 1}
EditorState = {tabbed horizontal 1} {/home/slayer/wbgen2_svn/wbgen2/examples/interrupts/run.do 0 0} {/home/slayer/wbgen2_svn/wbgen2/examples/RAMs/testbench.v 0 1}
Project_Major_Version = 6
Project_Minor_Version = 2
set input_wb_file "rams.wb"
set test_module "wb_test_rams"
set target "classic"
set lang "vhdl"
set library_files {
"../../lib/wbgen2_pkg.vhd"
"../../lib/altera/wbgen2_dpssram.vhd"
};
mkdir -p output
vlib work
vlib wbgen2
../../wbgen2.lua rams.wb -vo ./output/wb_slave_test_rams.vhdl -consto ./output/vlog_constants.v -co ./output/test_rams.h
foreach file $library_files { vcom -work wbgen2 $file }
if { $lang == "vhdl" } {
set target_filename [format "./output/%s.vhd" $test_module ]
set target_wb "+define+WB_USE_CLASSIC"
set wbgen_opt "-target classic"
} else {
set target_filename [format "./output/%s.v" $test_module ]
set target_wb "+define+WB_USE_PIPELINED"
set wbgen_opt "-target pipelined"
}
puts $target_filename
vcom -work wbgen2 ../../lib/wbgen2_pkg.vhd
vcom -work wbgen2 ../../lib/wbgen2_dpssram.vhd
vcom -work work ./output/wb_slave_test_rams.vhdl
../../wbgen2 $input_wb_file -vo $target_filename -consto ./output/vlog_constants.v -co ./output/regdefs.h -lang $lang $wbgen_opt
if { $lang == "verilog" } {
vlog -work work -work wbgen2 $target_filename
} else {
vcom -work work $target_filename
}
vlog ./testbench.v
vsim work.main
radix -hexadecimal
do wave.do
run 1000us
run 100us
wave zoomfull
set input_wb_file "rams.wb"
set test_module "wb_test_rams"
set target "classic"
set lang "vhdl"
set library_files {
"../../lib/wbgen2_pkg.vhd"
"../../lib/altera/wbgen2_dpssram.vhd"
};
vlib work
vlib wbgen2
../../wbgen2 rams.wb -vo ./output/wb_test_interrupts.vhd -consto ./output/vlog_constants.v -co ./output/test_interrupts.h
foreach file $library_files { vcom -work wbgen2 $file }
if { $lang == "vhdl" } {
set target_filename [format "./output/%s.vhd" $test_module ]
set target_wb "+define+WB_USE_CLASSIC"
set wbgen_opt "-target classic"
} else {
set target_filename [format "./output/%s.v" $test_module ]
set target_wb "+define+WB_USE_PIPELINED"
set wbgen_opt "-target pipelined"
}
puts $target_filename
vcom -work wbgen2 ../../lib/wbgen2_pkg.vhd
vcom -work wbgen2 ../../lib/wbgen2_eic.vhd
vcom -work work ./output/wb_test_interrupts.vhd
../../wbgen2 $input_wb_file -vo $target_filename -consto ./output/vlog_constants.v -co ./output/regdefs.h -lang $lang $wbgen_opt
if { $lang == "verilog" } {
vlog -work work -work wbgen2 $target_filename
} else {
vcom -work work $target_filename
}
vlog ./testbench.v
vsim work.main
radix -hexadecimal
do wave.do
run 1000us
run 100us
wave zoomfull
......@@ -4,187 +4,232 @@
`define async_clk_period 63
`include "output/vlog_constants.v"
`include "../common/wishbone_test_master.v"
module main;
reg clk=1;
reg ram1_clk = 1;
reg [31:0] rval;
module RAM_TEST_MASTER (input wb_clk_i,
input wb_rst_n_i);
parameter RAM_WIDTH = 32;
parameter RAM_ASYNC_CLOCK = 0;
parameter MAX_BLOCK_SIZE = 1024;
reg rst=0;
// generate clocks & reset
always #(`wbclk_period/2) clk <= ~clk;
always #(`async_clk_period/2) ram1_clk <= ~ram1_clk;
wire ram_clk;
reg clk_gen_reg = 1;
initial #1000 rst <= 1;
reg [RAM_WIDTH-1:0] buffer [0:MAX_BLOCK_SIZE-1];
reg [31:0] ram_addr = 0;
reg [RAM_WIDTH-1:0] ram_data_o = 0;
wire [RAM_WIDTH-1:0] ram_data_i;
reg ram_rd = 0;
reg ram_wr = 0;
reg [RAM_WIDTH/8-1:0] ram_bwsel = 'hff;
time last_op_time = 0;
reg last_op_rw = 0;
reg [31:0] last_addr = 0;
reg ready= 0;
`include "wishbone_stuff.v"
initial begin
@(posedge wb_rst_n_i);
#1000 ready = 1;
end
if(RAM_ASYNC_CLOCK == 0)
assign ram_clk = wb_clk_i;
else begin
always #(RAM_ASYNC_CLOCK/2) clk_gen_reg = ~clk_gen_reg;
assign ram_clk = clk_gen_reg;
end
reg [7:0] ram1_addr = 0;
reg [31:0] ram1_data_wr = 0;
wire [31:0] ram1_data_rd;
reg [3:0] ram1_bwsel = 4'b1111;
reg ram1_wr = 0, ram1_rd = 0;
reg [9:0] ram2_addr = 0;
wire [15:0] ram2_data_rd;
reg ram2_rd = 0;
task ram1_read;
input[31:0] addr;
output [31:0] data;
function addr_2_bwsel;
input [31:0] addr;
begin
ram1_addr = {2'b00, addr[9:2]};
ram1_rd = 1;
case(RAM_WIDTH)
8: addr_2_bwsel = 1'b1;
16: addr_2_bwsel = (addr[0] ? 2'b01: 2'b10);
32: begin
case (addr[1:0])
0: addr_2_bwsel = 4'b1000;
1: addr_2_bwsel = 4'b0100;
2: addr_2_bwsel = 4'b0010;
3: addr_2_bwsel = 4'b0001;
endcase // case(addr[1:0])
end
endcase // case(RAM_WIDTH)
end
endfunction // addr_2_bwsel
@(posedge ram1_clk);
task write_block;
input [31:0] addr;
input [3:0] size;
input [31:0] n_transfers;
begin : ram_writeblk_body
integer i;
#1 data = ram1_data_rd;
ram1_rd = 0;
if($time != last_op_time) begin
@(posedge ram_clk);
end
for (i=0;i<n_transfers;i=i+size) begin
ram_addr <= (i+addr) >> 2;
ram_bwsel <= 4'b1111; //addr_2_bwsel(i+addr);
ram_data_o <= buffer[i];
ram_wr <= 1;
@(posedge ram_clk);
ram_wr <= 0;
end
last_op_time = $time;
end
endtask // wb_write
task ram1_write;
input[31:0] addr;
input [31:0] data;
begin
#1 ram1_addr = {2'b00, addr[9:2]};
ram1_data_wr = data;
ram1_wr = 1;
@(posedge ram1_clk);
endtask
#1 ram1_wr = 0;
task write8;
input[31:0] addr;
input[7:0] data;
begin : write8_body
buffer[0] = data;
write_block(addr, 1, 1);
end
endtask
end
task write32;
input[31:0] addr;
input[31:0] data;
begin : write32_body
buffer[0] = data;
write_block(addr, 4, 1);
end
endtask
endmodule // RAM_TEST_MASTER
task ram2_read;
input[31:0] addr;
output [31:0] data;
begin
#1 ram2_addr = {2'b00, addr[11:2]};
ram2_rd = 1;
module main;
reg [31:0] rval;
@(posedge clk);
// generate clocks & reset
#1 data = ram2_data_rd;
ram2_rd = 0;
end
endtask // wb_write
WB_TEST_MASTER WB();
RAM_TEST_MASTER
#(.RAM_ASYNC_CLOCK(67))
RAM1 (
.wb_clk_i(WB.wb_clk),
.wb_rst_n_i(WB.wb_rst));
wb_slave_test_rams
dut(
.rst_n_i (rst),
.wb_clk_i (clk),
.wb_addr_i (wb_addr[10:0]),
.wb_data_i (wb_data_o),
.wb_data_o (wb_data_i),
.wb_cyc_i (wb_cyc),
.wb_sel_i (wb_bwsel),
.wb_stb_i (wb_stb),
.wb_we_i (wb_we),
.wb_ack_o (wb_ack),
.clk1_i (ram1_clk),
.rams_mem1k_addr_i (ram1_addr),
.rams_mem1k_data_o (ram1_data_rd),
.rams_mem1k_rd_i (ram1_rd),
.rams_mem1k_data_i (ram1_data_wr),
.rams_mem1k_wr_i (ram1_wr),
.rams_mem1k_bwsel_i (ram1_bwsel),
.rams_mem2k_addr_i (ram2_addr),
.rams_mem2k_data_o (ram2_data_rd),
.rams_mem2k_rd_i (ram2_rd)
);
wb_slave_test_rams
dut (
.rst_n_i (WB.wb_rst),
.wb_clk_i (WB.wb_clk),
.wb_addr_i(WB.wb_addr[10:0]),
.wb_data_i(WB.wb_data_o),
.wb_data_o(WB.wb_data_i),
.wb_cyc_i (WB.wb_cyc),
.wb_sel_i (WB.wb_bwsel),
.wb_stb_i (WB.wb_stb),
.wb_we_i (WB.wb_we),
.wb_ack_o (WB.wb_ack),
.clk1_i (RAM1.ram_clk),
.rams_mem1k_addr_i (RAM1.ram_addr[7:0]),
.rams_mem1k_data_o (RAM1.ram_data_i),
.rams_mem1k_rd_i (RAM1.ram_rd),
.rams_mem1k_data_i (RAM1.ram_data_o),
.rams_mem1k_wr_i (RAM1.ram_wr),
.rams_mem1k_bwsel_i(RAM1.ram_bwsel),
.rams_mem2k_addr_i (10'b0),
.rams_mem2k_data_o (),
.rams_mem2k_rd_i (1'b0)
);
integer i;
integer fail = 0;
initial begin
#2000; @(posedge clk); #1; // wait until the DUT is reset
wait(RAM1.ready && WB.ready);
$display("Test simple bus reads/writes...");
wb_verbose(1);
WB.verbose(1);
wb_write(`BASE_RAMS_MEM1K, 32'hdeadbeef);
wb_write(`BASE_RAMS_MEM1K + 4, 32'hcafecafe);
wb_write(`BASE_RAMS_MEM1K + 'h200, 32'hfacedead);
WB.write32(`BASE_RAMS_MEM1K, 32'hdeadbeef);
WB.write32(`BASE_RAMS_MEM1K + 4, 32'hcafecafe);
WB.write32(`BASE_RAMS_MEM1K + 'h200, 32'hfacedead);
wb_read(`BASE_RAMS_MEM1K, rval); if(rval != 'hdeadbeef) fail = 1;
wb_read(`BASE_RAMS_MEM1K + 4, rval);if(rval != 'hcafecafe) fail = 1;
wb_read(`BASE_RAMS_MEM1K + 'h200, rval);if(rval != 'hfacedead) fail = 1;
WB.read32(`BASE_RAMS_MEM1K, rval); if(rval != 'hdeadbeef) fail = 1;
WB.read32(`BASE_RAMS_MEM1K + 4, rval);if(rval != 'hcafecafe) fail = 1;
WB.read32(`BASE_RAMS_MEM1K + 'h200, rval);if(rval != 'hfacedead) fail = 1;
$display("Test mirrored bus reads/writes...");
wb_write(`BASE_RAMS_MEM1K + 16, 32'h55555555);
wb_read(`BASE_RAMS_MEM1K + 16, rval);if(rval != 'h55555555) fail = 1;
WB.write32(`BASE_RAMS_MEM1K + 16, 32'h55555555);
WB.read32(`BASE_RAMS_MEM1K + 16, rval);if(rval != 'h55555555) fail = 1;
wb_write(`BASE_RAMS_MEM1K + 4*`SIZE_RAMS_MEM1K + 16, 32'haaaaaaaa);
wb_read(`BASE_RAMS_MEM1K + 16, rval);if(rval != 'haaaaaaaa) fail = 1;
WB.write32(`BASE_RAMS_MEM1K + 4*`SIZE_RAMS_MEM1K + 16, 32'haaaaaaaa);
WB.read32(`BASE_RAMS_MEM1K + 16, rval);if(rval != 'haaaaaaaa) fail = 1;
$display("Byte-access test...");
wb_verbose(0);
WB.verbose(0);
for(i=0;i<32;i=i+1) wb_write_byte(`BASE_RAMS_MEM1K + i, i + 1);
/* for(i=0;i<32;i=i+1) WB.write8(`BASE_RAMS_MEM1K + i, i + 1);
for(i=0;i<32;i=i+1) begin
wb_read_byte(`BASE_RAMS_MEM1K + i, rval);
WB.read8(`BASE_RAMS_MEM1K + i, rval);
if(rval != i+1)
fail = 1;
end
*/
/*
$display("mem1k: Bus write/mem read test...");
for(i=0;i<256;i=i+1) wb_write(`BASE_RAMS_MEM1K + i*4, i+1);
@(posedge ram1_clk); // sync ourselves to the edge of RAM1 async clock
for(i=0;i<256;i=i+1) WB.write32(`BASE_RAMS_MEM1K + i*4, i+1);
for(i=0;i<256;i=i+1) begin
ram1_read(i*4, rval);
// RAM1.read32(i*4, rval);
if(rval != i+1) fail =1;
end
*/
$display("mem1k: Mem write/bus read test...");
for(i=0;i<256;i=i+1)
ram1_write(i*4, 257-i);
RAM1.write32(i*4, 257-i);
@(posedge clk); // sync back to wb clock
for(i=0;i<256;i=i+1) begin
wb_read(`BASE_RAMS_MEM1K+i*4, rval);
for(i=0;i<2;i=i+1) begin
WB.read32(`BASE_RAMS_MEM1K+i*4, rval);
$display(rval);
if(rval != 257-i)
fail =1;
end
end
/*
$display("mem2k: Bus write/mem read test...");
......@@ -207,6 +252,7 @@ module main;
else
$display("TESTS PASSED");
end
-----/\----- EXCLUDED -----/\----- */
endmodule
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /main/dut/rst_n_i
add wave -noupdate -format Logic /main/dut/wb_clk_i
add wave -noupdate -format Literal /main/dut/wb_addr_i
add wave -noupdate -format Literal /main/dut/wb_data_i
add wave -noupdate -format Literal /main/dut/wb_data_o
add wave -noupdate -format Logic /main/dut/wb_cyc_i
add wave -noupdate -format Literal /main/dut/wb_sel_i
add wave -noupdate -format Logic /main/dut/wb_stb_i
add wave -noupdate -format Logic /main/dut/wb_we_i
add wave -noupdate -format Logic /main/dut/wb_ack_o
add wave -noupdate -format Logic /main/dut/rams_mem1k_raminst/clk_a_i
add wave -noupdate -format Logic /main/dut/rams_mem1k_raminst/clk_b_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/addr_a_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/addr_b_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/data_a_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/data_a_o
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/data_b_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/data_a_o
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/data_b_o
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/bwsel_a_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/bwsel_b_i
add wave -noupdate -format Logic /main/dut/rams_mem1k_raminst/rd_a_i
add wave -noupdate -format Logic /main/dut/rams_mem1k_raminst/rd_b_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/data_b_o
add wave -noupdate -format Logic /main/dut/rams_mem1k_raminst/wr_a_i
add wave -noupdate -format Logic /main/dut/rams_mem1k_raminst/wr_b_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/clksel
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/bwsel_int_a
add wave -noupdate -format Literal /main/dut/rams_mem1k_raminst/bwsel_int_b
add wave -noupdate -format Logic /main/dut/rst_n_i
add wave -noupdate -format Logic /main/dut/wb_clk_i
add wave -noupdate -format Literal /main/dut/wb_addr_i
add wave -noupdate -format Literal /main/dut/wb_data_i
add wave -noupdate -format Literal /main/dut/wb_data_o
add wave -noupdate -format Logic /main/dut/wb_cyc_i
add wave -noupdate -format Literal /main/dut/wb_sel_i
add wave -noupdate -format Logic /main/dut/wb_stb_i
add wave -noupdate -format Logic /main/dut/wb_we_i
add wave -noupdate -format Logic /main/dut/wb_ack_o
add wave -noupdate -format Logic /main/dut/clk1_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_addr_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_data_o
add wave -noupdate -format Logic /main/dut/rams_mem1k_rd_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_data_i
add wave -noupdate -format Logic /main/dut/rams_mem1k_wr_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_bwsel_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_addr_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_data_o
add wave -noupdate -format Logic /main/dut/rams_mem2k_rd_i
add wave -noupdate -format Literal /main/dut/rams_mem1k_rddata_int
add wave -noupdate -format Logic /main/dut/rams_mem1k_rd_int
add wave -noupdate -format Logic /main/dut/rams_mem1k_wr_int
add wave -noupdate -format Literal /main/dut/rams_mem2k_rddata_int
add wave -noupdate -format Logic /main/dut/rams_mem2k_rd_int
add wave -noupdate -format Logic /main/dut/rams_mem2k_wr_int
add wave -noupdate -format Literal /main/dut/ack_sreg
add wave -noupdate -format Literal /main/dut/rddata_reg
add wave -noupdate -format Literal /main/dut/wrdata_reg
add wave -noupdate -format Literal /main/dut/bwsel_reg
add wave -noupdate -format Literal /main/dut/rwaddr_reg
add wave -noupdate -format Logic /main/dut/ack_in_progress
add wave -noupdate -format Logic /main/dut/wr_int
add wave -noupdate -format Logic /main/dut/rd_int
add wave -noupdate -format Logic /main/dut/bus_clock_int
add wave -noupdate -format Literal /main/dut/allones
add wave -noupdate -format Literal /main/dut/allzeros
add wave -noupdate -format Logic /main/dut/rams_mem2k_raminst/clk_a_i
add wave -noupdate -format Logic /main/dut/rams_mem2k_raminst/clk_b_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/addr_a_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/addr_b_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/data_a_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/data_b_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/data_a_o
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/data_b_o
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/bwsel_a_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/bwsel_b_i
add wave -noupdate -format Logic /main/dut/rams_mem2k_raminst/rd_a_i
add wave -noupdate -format Logic /main/dut/rams_mem2k_raminst/rd_b_i
add wave -noupdate -format Logic /main/dut/rams_mem2k_raminst/wr_a_i
add wave -noupdate -format Logic /main/dut/rams_mem2k_raminst/wr_b_i
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/clksel
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/bwsel_int_a
add wave -noupdate -format Literal /main/dut/rams_mem2k_raminst/bwsel_int_b
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {192662970 ps} 0}
WaveRestoreCursors {{Cursor 1} {20259630 ps} 0}
configure wave -namecolwidth 524
configure wave -valuecolwidth 100
configure wave -justifyvalue left
......@@ -96,4 +32,4 @@ configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
update
WaveRestoreZoom {0 ps} {1050148864 ps}
WaveRestoreZoom {99610350 ps} {100020508 ps}
......@@ -804,6 +804,6 @@ XML_DoubleClick = Edit
XML_CustomDoubleClick =
LOGFILE_DoubleClick = Edit
LOGFILE_CustomDoubleClick =
EditorState = {tabbed horizontal 1} {/home/slayer/wbgen2_svn/wbgen2/examples/interrupts/run.do 0 1}
EditorState = {tabbed horizontal 1} {/home/slayer/wbgen2_svn/wbgen2/examples/interrupts/run.do 0 0}
Project_Major_Version = 6
Project_Minor_Version = 2
......@@ -12,25 +12,29 @@ peripheral {
irq {
name = "Edge-positive";
name = "Rising edge IRQ";
description = "Rising-edge triggered IRQ line: interrupt is triggered when logic state on the input changes from 0 to 1";
prefix = "ipe";
trigger = EDGE_RISING;
};
irq {
name = "Edge-negative";
name = "Falling edge IRQ";
description = "Falling-edge triggered IRQ line: interrupt is triggered when logic state on the input changes from 1 to 0";
prefix = "ine";
trigger = EDGE_FALLING;
};
irq {
name = "Level-0";
name = "Level-0 IRQ";
description = "Hi-level triggered IRQ line: interrupt is active when state of the input is 0. Interrupt can be only cleared by changing the input state back to 1.";
prefix = "il0";
trigger = LEVEL_0;
};
irq {
name = "Level-1";
name = "Level-1 IRQ";
description = "Lo-level triggered IRQ line: interrupt is active when state of the input is 1. Interrupt can be only cleared by changing the input state back to 0.";
prefix = "il1";
trigger = LEVEL_1;
};
......
library ieee;
use ieee.std_logic_1164.all;
library altera_mf;
use altera_mf.all;
library wbgen2;
use wbgen2.all;
entity wbgen2_dpssram is
generic (
g_data_width : natural;
g_size : natural;
g_addr_width : natural;
g_dual_clock : boolean := false;
g_use_bwsel : boolean := false);
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic
);
end wbgen2_dpssram;
architecture syn of wbgen2_dpssram is
component altsyncram
generic (
address_reg_b : string;
byteena_reg_b : string;
byte_size : natural;
clock_enable_input_a : string;
clock_enable_input_b : string;
clock_enable_output_a : string;
clock_enable_output_b : string;
indata_reg_b : string;
-- intended_device_family : string;
lpm_type : string;
numwords_a : natural;
numwords_b : natural;
operation_mode : string;
outdata_aclr_a : string;
outdata_aclr_b : string;
outdata_reg_a : string;
outdata_reg_b : string;
power_up_uninitialized : string;
read_during_write_mode_port_a : string;
read_during_write_mode_port_b : string;
widthad_a : natural;
widthad_b : natural;
width_a : natural;
width_b : natural;
width_byteena_a : natural;
width_byteena_b : natural;
wrcontrol_wraddress_reg_b : string);
port (
wren_a : in std_logic;
clock0 : in std_logic;
wren_b : in std_logic;
clock1 : in std_logic;
byteena_a : in std_logic_vector ((g_data_width+7)/8-1 downto 0);
byteena_b : in std_logic_vector ((g_data_width+7)/8-1 downto 0);
address_a : in std_logic_vector ((g_addr_width-1) downto 0);
address_b : in std_logic_vector ((g_addr_width-1) downto 0);
rden_a : in std_logic;
q_a : out std_logic_vector ((g_data_width-1) downto 0);
rden_b : in std_logic;
q_b : out std_logic_vector ((g_data_width-1) downto 0);
data_a : in std_logic_vector ((g_data_width-1) downto 0);
data_b : in std_logic_vector ((g_data_width-1) downto 0));
end component;
signal clksel : string(1 to 6);
signal bwsel_int_a : std_logic_vector((g_data_width+7)/8-1 downto 0);
signal bwsel_int_b : std_logic_vector((g_data_width+7)/8-1 downto 0);
begin -- syn
genram1: if(g_dual_clock = true) generate
altsyncram_component : altsyncram
generic map (
address_reg_b => "CLOCK1",
byteena_reg_b => "CLOCK1",
byte_size => 8,
clock_enable_input_a => "BYPASS",
clock_enable_input_b => "BYPASS",
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => "CLOCK1",
-- intended_device_family => "Cyclone III",
lpm_type => "altsyncram",
numwords_a => g_size,
numwords_b => g_size,
operation_mode => "BIDIR_DUAL_PORT",
outdata_aclr_a => "NONE",
outdata_aclr_b => "NONE",
outdata_reg_a => "UNREGISTERED",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "OLD_DATA",
read_during_write_mode_port_b => "OLD_DATA",
widthad_a => g_addr_width,
widthad_b => g_addr_width,
width_a => g_data_width,
width_b => g_data_width,
width_byteena_a => (g_data_width+7)/8,
width_byteena_b => (g_data_width+7)/8,
wrcontrol_wraddress_reg_b => "CLOCK1"
)
port map (
wren_a => wr_a_i,
wren_b => wr_b_i,
clock0 => clk_a_i,
clock1 => clk_b_i,
byteena_a => bwsel_int_a,
byteena_b => bwsel_int_b,
address_a => addr_a_i,
address_b => addr_b_i,
rden_a => rd_a_i,
rden_b => rd_b_i,
data_a => data_a_i,
data_b => data_b_i,
q_a => data_a_o,
q_b => data_b_o
);
end generate genram1;
genram2: if(g_dual_clock = false) generate
altsyncram_component : altsyncram
generic map (
address_reg_b => "CLOCK0",
byteena_reg_b => "CLOCK0",
byte_size => 8,
clock_enable_input_a => "BYPASS",
clock_enable_input_b => "BYPASS",
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => "CLOCK0",
-- intended_device_family => "Cyclone III",
lpm_type => "altsyncram",
numwords_a => g_size,
numwords_b => g_size,
operation_mode => "BIDIR_DUAL_PORT",
outdata_aclr_a => "NONE",
outdata_aclr_b => "NONE",
outdata_reg_a => "UNREGISTERED",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "OLD_DATA",
read_during_write_mode_port_b => "OLD_DATA",
widthad_a => g_addr_width,
widthad_b => g_addr_width,
width_a => g_data_width,
width_b => g_data_width,
width_byteena_a => (g_data_width+7)/8,
width_byteena_b => (g_data_width+7)/8,
wrcontrol_wraddress_reg_b => "CLOCK0"
)
port map (
wren_a => wr_a_i,
wren_b => wr_b_i,
clock0 => clk_a_i,
-- clock1 => clk_b_i,
byteena_a => bwsel_int_a,
byteena_b => bwsel_int_b,
address_a => addr_a_i,
address_b => addr_b_i,
rden_a => rd_a_i,
rden_b => rd_b_i,
data_a => data_a_i,
data_b => data_b_i,
q_a => data_a_o,
q_b => data_b_o
);
end generate genram2;
-- clksel <= ;
genbwsel1: if(g_use_bwsel = true) generate
bwsel_int_a <= bwsel_a_i;
bwsel_int_b <= bwsel_b_i;
end generate genbwsel1;
genbwsel2: if(g_use_bwsel = false) generate
bwsel_int_a <= (others => '1');
bwsel_int_b <= (others => '1');
end generate genbwsel2;
end syn;
library ieee;
use ieee.std_logic_1164.all;
library altera_mf;
use altera_mf.all;
library XilinxCoreLib;
use XilixCoreLib.all;
library wbgen2;
use wbgen2.all;
......@@ -55,7 +55,7 @@ architecture syn of wbgen2_dpssram is
clock_enable_output_a : string;
clock_enable_output_b : string;
indata_reg_b : string;
intended_device_family : string;
-- intended_device_family : string;
lpm_type : string;
numwords_a : natural;
numwords_b : natural;
......@@ -110,7 +110,7 @@ begin -- syn
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => "CLOCK1",
intended_device_family => "Cyclone III",
-- intended_device_family => "Cyclone III",
lpm_type => "altsyncram",
numwords_a => g_size,
numwords_b => g_size,
......
......@@ -3,26 +3,26 @@ MAX_ACK_LENGTH = 10;
function gen_wishbone_ports()
local ports = {
port(BIT, 0, "in", "rst_n_i"),
port(BIT, 0, "in", "wb_clk_i"),
port(BIT, 0, "in", "rst_n_i", "", true),
port(BIT, 0, "in", "wb_clk_i", "", true),
};
if(address_bus_width > 0 ) then
table_join(ports, { port(SLV, address_bus_width, "in", "wb_addr_i") });
table_join(ports, { port(SLV, address_bus_width, "in", "wb_addr_i", "", true) });
end
table_join(ports, {
port(SLV, DATA_BUS_WIDTH, "in", "wb_data_i"),
port(SLV, DATA_BUS_WIDTH, "out", "wb_data_o"),
port(BIT, 0, "in", "wb_cyc_i"),
port(SLV, math.floor((DATA_BUS_WIDTH+7)/8), "in", "wb_sel_i"),
port(BIT, 0, "in", "wb_stb_i"),
port(BIT, 0, "in", "wb_we_i"),
port(BIT, 0, "out", "wb_ack_o")
port(SLV, DATA_BUS_WIDTH, "in", "wb_data_i", "", true),
port(SLV, DATA_BUS_WIDTH, "out", "wb_data_o", "", true),
port(BIT, 0, "in", "wb_cyc_i", "", true),
port(SLV, math.floor((DATA_BUS_WIDTH+7)/8), "in", "wb_sel_i", "", true),
port(BIT, 0, "in", "wb_stb_i", "", true),
port(BIT, 0, "in", "wb_we_i", "", true),
port(BIT, 0, "out", "wb_ack_o", "", true)
});
if(periph.irqcount > 0) then
table_join(ports, { port(BIT, 0, "out" ,"wb_irq_o"); });
table_join(ports, { port(BIT, 0, "out" ,"wb_irq_o", "", true); });
end
......@@ -45,6 +45,7 @@ local wb_sigs = { signal(SLV, MAX_ACK_LENGTH, "ack_sreg"),
signal(BIT, 0, "bus_clock_int"),
signal(SLV, DATA_BUS_WIDTH, "allones"),
signal(SLV, DATA_BUS_WIDTH, "allzeros")
};
add_global_signals(wb_sigs);
......@@ -90,16 +91,22 @@ function gen_bus_logic_wishbone()
local acklen = find_max(reg, "acklen");
local rcode={};
local wcode={};
foreach_subfield(reg, function(field, reg) table_join(wcode, field.write_code); end );
foreach_subfield(reg, function(field, reg) table_join(rcode, field.read_code); end );
local padcode = fill_unused_bits("rddata_reg", reg);
table_join(wcode, reg.write_code);
table_join(rcode, reg.read_code);
local rwcode = {
vif(vequal("wb_we_i" ,1), {
wcode
wcode,
padcode
}, {
rcode
}); };
......@@ -172,7 +179,8 @@ function gen_bus_logic_wishbone()
va("wr_int", vand("wb_cyc_i", vand("wb_stb_i", "wb_we_i")));
va("allones", vothers(1));
va("allzeros", vothers(0));
vcomment("");
vcomment("Main register bank access process.");
......@@ -205,7 +213,7 @@ function gen_bus_logic_wishbone()
-- the data output is muxed between RAMs and register bank. Here we generate a combinatorial mux if we don't want the output to be registered. This gives us
-- memory access time of 2 clock cycles. Otherwise the ram output is handled by the main process.
if(not options.register_data_output) then
local sens_list = {"rddata_reg"};
local sens_list = {"rddata_reg","rwaddr_reg"};
local mux_switch_code = {};
local mux_code = {vswitch(vi("rwaddr_reg", address_bus_width-1, address_bus_width - address_bus_select_bits), mux_switch_code); };
......@@ -213,11 +221,16 @@ function gen_bus_logic_wishbone()
foreach_reg({TYPE_RAM}, function(reg)
table.insert(sens_list, reg.full_prefix.."_rddata_int");
table_join(mux_switch_code, {
vcase(reg.select_bits, {
va(vi("wb_data_o", reg.width-1, 0), reg.full_prefix.."_rddata_int");
} );
} );
local assign_code = { va(vi("wb_data_o", reg.width-1, 0), reg.full_prefix.."_rddata_int"); };
if(reg.width < DATA_BUS_WIDTH) then
table_join(assign_code, { va(vi("wb_data_o", DATA_BUS_WIDTH-1, reg.width), 0); });
end
table_join(mux_switch_code, { vcase(reg.select_bits, assign_code ); } );
end);
table.insert(sens_list, "wb_addr_i");
......
This diff is collapsed.
This diff is collapsed.
......@@ -118,10 +118,12 @@ function wbgen_generate_eic()
["__type"] = TYPE_FIELD;
["type"] = BIT;
["name"] = irq.name;
["description"] = "read 1: interrupt "..irq.name.." is pending<br>read 0: interrupt not pending<br>write 1: clear interrupt "..irq.name.."<br>write 0: no effect";
["description"] = "read 1: interrupt '"..irq.name.."' is pending\nread 0: interrupt not pending\nwrite 1: clear interrupt '"..irq.name.."'\nwrite 0: no effect";
["c_prefix"] = irq.c_prefix;
["hdl_prefix"] = irq.hdl_prefix;
["access"] = ACCESS_RW_RW;
["access_bus"] = READ_WRITE;
["access_dev"] = READ_WRITE;
};
local field_ier = {
......@@ -129,10 +131,12 @@ function wbgen_generate_eic()
["__type"] = TYPE_FIELD;
["type"] = BIT;
["name"] = irq.name;
["description"] = "write 1: enable interrupt "..irq.name.." <br>0: no effect";
["description"] = "write 1: enable interrupt '"..irq.name.."'\nwrite 0: no effect";
["c_prefix"] = irq.c_prefix;
["hdl_prefix"] = irq.hdl_prefix;
["access"] = ACCESS_WO_RO;
["access_bus"] = WRITE_ONLY;
["access_dev"] = READ_ONLY;
};
local field_idr = {
......@@ -140,10 +144,12 @@ function wbgen_generate_eic()
["__type"] = TYPE_FIELD;
["type"] = BIT;
["name"] = irq.name;
["description"] = "write 1: disable interrupt "..irq.name.." <br>0: no effect";
["description"] = "write 1: disable interrupt '"..irq.name.."'\nwrite 0: no effect";
["c_prefix"] = irq.c_prefix;
["hdl_prefix"] = irq.hdl_prefix;
["access"] = ACCESS_WO_RO;
["access_bus"] = WRITE_ONLY;
["access_dev"] = READ_ONLY;
};
local field_imr = {
......@@ -151,10 +157,13 @@ function wbgen_generate_eic()
["__type"] = TYPE_FIELD;
["type"] = BIT;
["name"] = irq.name;
["description"] = "read 1: interrupt "..irq.name.." is enabled <br>read 0: interrupt "..irq.name.."is disabled";
["description"] = "read 1: interrupt '"..irq.name.."' is enabled\nread 0: interrupt '"..irq.name.."' is disabled";
["c_prefix"] = irq.c_prefix;
["hdl_prefix"] = irq.hdl_prefix;
["access"] = ACCESS_RO_WO;
["access_bus"] = READ_ONLY;
["access_dev"] = WRITE_ONLY;
};
......@@ -217,6 +226,7 @@ function wbgen_generate_eic()
local fake_irq = {
["__type"] = TYPE_IRQ;
["no_docu"] = true;
["name"] = "IRQ_CONTROLLER";
["prefix"] = "IRQ_CONTROLLER";
["extra_code"] = irq_unit_code;
......
This diff is collapsed.
......@@ -115,4 +115,6 @@ function gen_code_ram(ram)
vinstance (prefix.."_raminst", "wbgen2_dpssram", ram.maps );
};
ram.base = ram.select_bits * math.pow (2, address_bus_width - address_bus_select_bits);
end
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment