URL
https://opencores.org/ocsvn/tv80/tv80/trunk
Subversion Repositories tv80
Compare Revisions
- This comparison shows the changes necessary to convert path
/tv80/trunk
- from Rev 109 to Rev 110
- ↔ Reverse comparison
Rev 109 → Rev 110
/doc/rgen_doc.html
0,0 → 1,451
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" dir="ltr" lang="en"><head> |
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>rgen.py [TV80 Design]</title> |
|
|
<meta name="generator" content="DokuWiki Release rc2006-10-08"> |
<meta name="robots" content="index,follow"> |
<meta name="date" content="2011-02-24T16:12:15-0800"> |
<meta name="keywords" content="rgen.py"> |
<link rel="start" href="http://192.168.1.1/dokuwiki/"> |
<link rel="contents" href="http://192.168.1.1/dokuwiki/doku.php?id=rgen.py&do=index" title="Index"> |
<link rel="alternate" type="application/rss+xml" title="Recent Changes" href="http://192.168.1.1/dokuwiki/feed.php"> |
<link rel="alternate" type="application/rss+xml" title="Current Namespace" href="http://192.168.1.1/dokuwiki/feed.php?mode=list&ns="> |
<link rel="alternate" type="text/html" title="Plain HTML" href="http://192.168.1.1/dokuwiki/doku.php?do=export_xhtml&id=rgen.py"> |
<link rel="alternate" type="text/plain" title="Wiki Markup" href="http://192.168.1.1/dokuwiki/doku.php?do=export_raw&id=rgen.py"> |
<link rel="stylesheet" media="screen" type="text/css" href="rgen_doc_files/css.php"> |
<link rel="stylesheet" media="print" type="text/css" href="rgen_doc_files/css_002.php"> |
<script type="text/javascript" charset="utf-8" src="rgen_doc_files/js.php"></script> |
|
<link rel="shortcut icon" href="http://192.168.1.1/dokuwiki/lib/tpl/default/images/favicon.ico"></head><body> |
<div class="dokuwiki"> |
|
<div class="stylehead"> |
|
<div class="header"> |
<div class="pagename"> |
[[<a href="http://192.168.1.1/dokuwiki/doku.php?id=rgen.py&do=backlink">rgen.py</a>]] |
</div> |
<div class="logo"> |
<a href="http://192.168.1.1/dokuwiki/doku.php?id=" name="dokuwiki__top" id="dokuwiki__top" accesskey="h" title="[ALT+H]">TV80 Design</a> </div> |
|
<div class="clearer"></div> |
</div> |
|
|
<div class="bar" id="bar__top"> |
<div class="bar-left" id="bar__topleft"> |
<form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="rev" value="" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit this page" class="button" accesskey="e" title="Edit this page [ALT+E]" type="submit"></div></form> <form class="button" method="get" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="revisions" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Old revisions" class="button" accesskey="o" title="Old revisions [ALT+O]" type="submit"></div></form> </div> |
|
<div class="bar-right" id="bar__topright"> |
<form class="button" method="get" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="recent" type="hidden"><input name="id" value="" type="hidden"><input value="Recent changes" class="button" accesskey="r" title="Recent changes [ALT+R]" type="submit"></div></form> <form action="/dokuwiki/doku.php?id=" accept-charset="utf-8" class="search" id="dw__search"><div class="no"><input name="do" value="search" type="hidden"><input id="qsearch__in" accesskey="f" name="id" class="edit" title="[ALT+F]" type="text"><input value="Search" class="button" title="Search" type="submit"><div id="qsearch__out" class="ajax_qsearch JSpopup"></div></div></form> |
</div> |
|
<div class="clearer"></div> |
</div> |
|
<div class="breadcrumbs"> |
Trace: <span class="bcsep">»</span> <a href="http://192.168.1.1/dokuwiki/doku.php?id=start" class="breadcrumbs" title="start">start</a> <span class="bcsep">»</span> <span class="curid"><a href="http://192.168.1.1/dokuwiki/doku.php?id=rgen.py" class="breadcrumbs" title="rgen.py">rgen.py</a></span> </div> |
|
|
</div> |
|
|
<div class="page"> |
<!-- wikipage start --> |
<div class="toc"> |
<div class="tocheader toctoggle" id="toc__header"><img alt="-" src="rgen_doc_files/arrow_up.gif" id="toc__hide"><img style="display: none;" alt="+" src="rgen_doc_files/arrow_down.gif" id="toc__show">Table of Contents</div> |
<div id="toc__inside"> |
|
<ul class="toc"> |
<li class="level1"><div class="li"><span class="li"><a href="#rgen_register_file_and_decoder_generator" class="toc">rgen Register File and Decoder Generator</a></span></div></li> |
<li class="level1"><div class="li"><span class="li"><a href="#register_file_generator" class="toc">Register File Generator</a></span></div> |
<ul class="toc"> |
<li class="level2"><div class="li"><span class="li"><a href="#tag_definitions" class="toc">Tag Definitions</a></span></div> |
<ul class="toc"> |
<li class="level3"><div class="li"><span class="li"><a href="#config" class="toc">config</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#status" class="toc">status</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#count" class="toc">count</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#int_msk" class="toc">int_msk</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#soft_set" class="toc">soft_set</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#write_stb" class="toc">write_stb</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#read_stb" class="toc">read_stb</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#ext_load" class="toc">ext_load</a></span></div></li> |
<li class="level3"><div class="li"><span class="li"><a href="#user" class="toc">user</a></span></div></li> |
</ul> |
</li> |
</ul> |
</li> |
<li class="level1"><div class="li"><span class="li"><a href="#decoder_generator" class="toc">Decoder Generator</a></span></div></li></ul> |
</div> |
</div> |
|
|
|
<h1><a name="rgen_register_file_and_decoder_generator" id="rgen_register_file_and_decoder_generator">rgen Register File and Decoder Generator</a></h1> |
<div class="level1"> |
|
<p> rgen is a Python script for generating a hierarchical set of |
register files and address decoders. It supports a variety of register |
types and multiple levels of address decoding hieararchy. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="1-248" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="rgen Register File and Decoder Generator" type="submit"></div></form></div> |
<h1><a name="register_file_generator" id="register_file_generator">Register File Generator</a></h1> |
<div class="level1"> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="249-286" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="Register File Generator" type="submit"></div></form></div> |
<h2><a name="tag_definitions" id="tag_definitions">Tag Definitions</a></h2> |
<div class="level2"> |
<table class="inline"> |
<tbody><tr> |
<th>tag name</th><th>attributes</th><th>description</th> |
</tr> |
<tr> |
<td>tv_registers</td><td>name,addr_sz,data_sz,base_addr,registered_read</td><td>top-level tag for a register file</td> |
</tr> |
<tr> |
<td>register</td><td>name,type,width,default</td><td>tag for a single logical register</td> |
</tr> |
<tr> |
<td>field</td><td>name,width,default</td><td>tag for a bit field within a single register</td> |
</tr> |
</tbody></table> |
<table class="inline"> |
<tbody><tr> |
<th>register type</th><th>Access</th><th>description</th> |
</tr> |
<tr> |
<td><a href="#config" title="rgen.py ↵" class="wikilink1">config</a></td><td>RW</td><td>General read-write configuration register</td> |
</tr> |
<tr> |
<td><a href="#status" title="rgen.py ↵" class="wikilink1">status</a></td><td>RO</td><td>Read-only status register</td> |
</tr> |
<tr> |
<td><a href="#count" title="rgen.py ↵" class="wikilink1">count</a></td><td>RW</td><td>Incrementing statistics register</td> |
</tr> |
<tr> |
<td><a href="#int_msk" title="rgen.py ↵" class="wikilink1">int_msk</a></td><td>Special</td><td>Interrupt status & mask registers</td> |
</tr> |
<tr> |
<td><a href="#soft_set" title="rgen.py ↵" class="wikilink1">soft_set</a></td><td>RW</td><td>Software set, hardware clear register</td> |
</tr> |
<tr> |
<td><a href="#write_stb" title="rgen.py ↵" class="wikilink1">write_stb</a></td><td>RW</td><td>Configuration register with additional strobe output</td> |
</tr> |
<tr> |
<td><a href="#read_stb" title="rgen.py ↵" class="wikilink1">read_stb</a></td><td>RW</td><td>Configuration register with additional strobe outout</td> |
</tr> |
<tr> |
<td><a href="#ext_load" title="rgen.py ↵" class="wikilink1">ext_load</a></td><td>RW</td><td>External-load register</td> |
</tr> |
<tr> |
<td><a href="#user" title="rgen.py ↵" class="wikilink1">user</a></td><td>Special</td><td>User-defined pass-through register</td> |
</tr> |
</tbody></table> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="287-1131" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="Tag Definitions" type="submit"></div></form></div> |
<h3><a name="config" id="config">config</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME</td><td>output</td><td>WIDTH</td><td>Read-only value of config bits</td> |
</tr> |
</tbody></table> |
|
<p> |
Basic configuration register, read/write by the configuration side, register bits available read-only from the hardware side. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="1132-1367" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="config" type="submit"></div></form></div> |
<h3><a name="status" id="status">status</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME</td><td>input</td><td>WIDTH</td><td>status input bits</td> |
</tr> |
</tbody></table> |
|
<p> |
Status register, read-only by the config side, status bits are combinatorial input from the hardware side. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="1368-1570" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="status" type="submit"></div></form></div> |
<h3><a name="count" id="count">count</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME</td><td>output</td><td>WIDTH</td><td>current count value</td> |
</tr> |
<tr> |
<td>NAME_inc</td><td>input</td><td>1</td><td>When high, increment count by 1</td> |
</tr> |
</tbody></table> |
|
<p> Basic statistics register. Read/write by config side, count value |
available read-only from hardware side. Increment value provided for |
hardware side. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="1571-1871" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="count" type="submit"></div></form></div> |
<h3><a name="int_msk" id="int_msk">int_msk</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME_set</td><td>input</td><td>WIDTH</td><td>set interrupt</td> |
</tr> |
</tbody></table> |
|
<p> The int_msk register type provides a pair of interrupt registers. |
The first register is the interrupt status register, and the second is |
the interrupt mask register. The interrupt status register can be set |
by hardware and cleared by software by writing a ‘1’ to the bit which |
should be cleared. Software cannot set any bits in the interrupt |
register, and writing ‘0’ to a bit has no effect (leave unchanged). |
</p> |
|
<p>The paired mask register has the same number of bits as the status |
register, but each bit set in the mask register disables interrupt |
generation for the corresponding status bit. Note that even if |
interrupt generation is disabled, the status bit will still be set. The |
mask register is Read/Write by software. |
</p> |
|
<p>The default attribute for this register type sets the default value |
of the mask register; the default value of the status register is |
always zero. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="1872-2842" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="int_msk" type="submit"></div></form></div> |
<h3><a name="soft_set" id="soft_set">soft_set</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME</td><td>output</td><td>WIDTH</td><td>Read-only value of config bits</td> |
</tr> |
<tr> |
<td>NAME_clr</td><td>input</td><td>WIDTH</td><td>Read-only value of config bits</td> |
</tr> |
</tbody></table> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="2843-3007" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="soft_set" type="submit"></div></form></div> |
<h3><a name="write_stb" id="write_stb">write_stb</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME</td><td>output</td><td>WIDTH</td><td>Read-only value of config bits</td> |
</tr> |
<tr> |
<td>NAME_wr_stb</td><td>output</td><td>1</td><td>Pulses on write to this register</td> |
</tr> |
</tbody></table> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="3008-3175" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="write_stb" type="submit"></div></form></div> |
<h3><a name="read_stb" id="read_stb">read_stb</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME</td><td>output</td><td>WIDTH</td><td>Read-only value of config bits</td> |
</tr> |
<tr> |
<td>NAME_wr_stb</td><td>output</td><td>1</td><td>Pulses on read to this register</td> |
</tr> |
</tbody></table> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="3176-3341" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="read_stb" type="submit"></div></form></div> |
<h3><a name="ext_load" id="ext_load">ext_load</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME_out</td><td>output</td><td>WIDTH</td><td>Data from config interface</td> |
</tr> |
<tr> |
<td>NAME_in</td><td>input</td><td>WIDTH</td><td>Sample data in to config interface</td> |
</tr> |
<tr> |
<td>NAME_wr_stb</td><td>output</td><td>1</td><td>Pulsed on final write operation</td> |
</tr> |
<tr> |
<td>NAME_rd_stb</td><td>output</td><td>1</td><td>Pulsed on initial read operation</td> |
</tr> |
</tbody></table> |
|
<p> An external-load register is used to sample and cache values which |
may be changing over time. It is intended to be used for values which |
are wider than the configuration interface (otherwise, a <a href="#status" title="rgen.py ↵" class="wikilink1">status</a> or <a href="#write_stb" title="rgen.py ↵" class="wikilink1">write_stb</a> |
register would be more appropriate). The width of an ext_load register |
can be wider than the data_sz width of the module, and rgen will split |
the logical register into multiple physical registers. |
</p> |
|
<p> |
Current limitations: ext_load registers must be an even multiple of data_size otherwise syntax errors will result. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="3342-4161" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="ext_load" type="submit"></div></form></div> |
<h3><a name="user" id="user">user</a></h3> |
<div class="level3"> |
<table class="inline"> |
<tbody><tr> |
<th>port name</th><th>direction</th><th>size</th><th>description</th> |
</tr> |
<tr> |
<td>NAME_wr_data</td><td>output</td><td>WIDTH</td><td>Data from config on write</td> |
</tr> |
<tr> |
<td>NAME_wr_stb</td><td>output</td><td>1</td><td>Asserted during write operation</td> |
</tr> |
<tr> |
<td>NAME_wr_ack</td><td>input</td><td>1</td><td>Assert by HW side to acknowledge write</td> |
</tr> |
<tr> |
<td>NAME_rd_data</td><td>input</td><td>WIDTH</td><td>Data to config on read</td> |
</tr> |
<tr> |
<td>NAME_rd_stb</td><td>output</td><td>1</td><td>Asserted during read operation</td> |
</tr> |
<tr> |
<td>NAME_rd_ack</td><td>input</td><td>1</td><td>Assert by HW side to acknowledge read</td> |
</tr> |
</tbody></table> |
|
<p> Register with user-defined behavior. Used to implement registers |
with read-side effects, or where config interface must arbitrate with |
the HW datapath for access to a resource. Provides full handshake for |
each of read and write operations. |
</p> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="4162-4794" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="user" type="submit"></div></form></div> |
<h1><a name="decoder_generator" id="decoder_generator">Decoder Generator</a></h1> |
<div class="level1"> |
|
<p> |
Decoders are created using a different set of tags from the register file generator. |
</p> |
<table class="inline"> |
<tbody><tr> |
<th>tag name</th><th>attributes</th><th>description</th> |
</tr> |
<tr> |
<td>it_decoder</td><td>name,addr_sz,data_sz</td><td>top-level tag for an address decoder</td> |
</tr> |
<tr> |
<td>range</td><td>prefix,base,bits</td><td>tag for an address decode range</td> |
</tr> |
</tbody></table> |
|
</div> |
<div class="secedit"><form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="lines" value="4795-" type="hidden"><input name="rev" value="1298592735" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit" class="button" title="Decoder Generator" type="submit"></div></form></div> |
<!-- wikipage stop --> |
</div> |
|
<div class="clearer"> </div> |
|
|
<div class="stylefoot"> |
|
<div class="meta"> |
<div class="user"> |
</div> |
<div class="doc"> |
rgen.py.txt · Last modified: 2011/02/24 16:12 by 10.81.24.204 </div> |
</div> |
|
|
<div class="bar" id="bar__bottom"> |
<div class="bar-left" id="bar__bottomleft"> |
<form class="button" method="post" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="edit" type="hidden"><input name="rev" value="" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Edit this page" class="button" accesskey="e" title="Edit this page [ALT+E]" type="submit"></div></form> <form class="button" method="get" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="revisions" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Old revisions" class="button" accesskey="o" title="Old revisions [ALT+O]" type="submit"></div></form> </div> |
<div class="bar-right" id="bar__bottomright"> |
<form class="button" method="get" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="login" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Login" class="button" title="Login" type="submit"></div></form> <form class="button" method="get" action="/dokuwiki/doku.php"><div class="no"><input name="do" value="index" type="hidden"><input name="id" value="rgen.py" type="hidden"><input value="Index" class="button" accesskey="x" title="Index [ALT+X]" type="submit"></div></form> <a class="nolink" href="#dokuwiki__top"><input class="button" value="Back to top" onclick="window.scrollTo(0, 0)" title="Back to top" type="button"></a> |
</div> |
<div class="clearer"></div> |
</div> |
|
</div> |
|
</div> |
|
<div class="footerinc"> |
<a href="http://192.168.1.1/dokuwiki/feed.php" title="Recent changes RSS feed"><img src="rgen_doc_files/button-rss.png" alt="Recent changes RSS feed" height="15" width="80"></a> |
|
<a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" rel="license" title="Creative Commons License"><img src="rgen_doc_files/button-cc.gif" alt="Creative Commons License" height="15" width="80"></a> |
|
<a href="https://www.paypal.com/xclick/business=andi%40splitbrain.org&item_name=DokuWiki+Donation&no_shipping=1&no_note=1&tax=0&currency_code=EUR&lc=US" title="Donate"><img src="rgen_doc_files/button-donate.gif" alt="Donate" height="15" width="80"></a> |
|
<a href="http://www.php.net/" title="Powered by PHP"><img src="rgen_doc_files/button-php.gif" alt="Powered by PHP" height="15" width="80"></a> |
|
<a href="http://validator.w3.org/check/referer" title="Valid XHTML 1.0"><img src="rgen_doc_files/button-xhtml.png" alt="Valid XHTML 1.0" height="15" width="80"></a> |
|
<a href="http://jigsaw.w3.org/css-validator/check/referer" title="Valid CSS"><img src="rgen_doc_files/button-css.png" alt="Valid CSS" height="15" width="80"></a> |
|
<a href="http://wiki.splitbrain.org/wiki:dokuwiki" title="Driven by DokuWiki"><img src="rgen_doc_files/button-dw.png" alt="Driven by DokuWiki" height="15" width="80"></a> |
|
|
|
<!-- |
|
<rdf:RDF xmlns="http://web.resource.org/cc/" |
xmlns:dc="http://purl.org/dc/elements/1.1/" |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> |
<Work rdf:about=""> |
<dc:type rdf:resource="http://purl.org/dc/dcmitype/Text" /> |
<license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.0/" /> |
</Work> |
|
<License rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.0/"> |
<permits rdf:resource="http://web.resource.org/cc/Reproduction" /> |
<permits rdf:resource="http://web.resource.org/cc/Distribution" /> |
<requires rdf:resource="http://web.resource.org/cc/Notice" /> |
<requires rdf:resource="http://web.resource.org/cc/Attribution" /> |
<prohibits rdf:resource="http://web.resource.org/cc/CommercialUse" /> |
<permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> |
<requires rdf:resource="http://web.resource.org/cc/ShareAlike" /> |
</License> |
|
</rdf:RDF> |
|
--> |
|
|
</div> |
|
<div class="no"><img src="rgen_doc_files/indexer.php" alt="" height="1" width="1"></div> |
</body></html> |
/scripts/rgen.py
1,4 → 1,4
#!/usr/bin/python |
#!/usr/bin/env python |
# Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
21,15 → 21,54
|
# This script generates I/O mapped control and status registers based |
# on an XML configuration file. |
# |
|
import reglib |
import xml.dom.minidom |
import sys, os, re |
import sys, os, re, string |
|
def node_info (node): |
print "Methods:",dir(node) |
print "Child Nodes:",node.childNodes |
|
def create_addr_vh (filename, dg): |
fh = open (filename, 'w') |
for d in dg.ranges: |
print repr(d) |
ba = d.get_base_addr() |
fh.write ("`define %s 'h%x\n" % (d.name.upper(), ba)) |
fh.close() |
|
def create_addr_decoder (node): |
rg = reglib.decoder_group() |
|
rg.name = node.getAttribute ("name") |
rg.addr_size = reglib.number(node.getAttribute ("addr_sz")) |
|
data_sz = node.getAttribute ("data_sz") |
if (data_sz != ''): |
rg.data_size = reglib.number(data_sz) |
|
return rg |
|
def create_decoder_verilog (top_node): |
dg = create_addr_decoder (top_node) |
|
# get list of address ranges |
range_nodes = top_node.getElementsByTagName ("range") |
for rn in range_nodes: |
prefix = rn.getAttribute ("prefix") |
base = reglib.number(rn.getAttribute ("base")) |
bits = int(rn.getAttribute ("bits")) |
r = reglib.decoder_range (prefix, base, bits) |
dg.add_range (r) |
|
fname = dg.name + ".v" |
fh = open (fname, 'w') |
fh.write (dg.verilog()) |
fh.close() |
create_addr_vh (dg.name + ".vh", dg) |
|
def create_reg_group (node): |
rg = reglib.register_group() |
|
37,6 → 76,14
rg.addr_size = reglib.number(node.getAttribute ("addr_sz")) |
rg.base_addr = reglib.number(node.getAttribute ("base_addr")) |
|
data_sz = node.getAttribute ("data_sz") |
if (data_sz != ''): |
rg.data_size = reglib.number(data_sz) |
|
rread = node.getAttribute ("registered_read") |
if (data_sz != ''): |
rg.registered_read = reglib.number(rread) |
|
return rg |
|
def create_register (rg, node): |
43,7 → 90,9
params = {} |
params['name'] = node.getAttribute ("name") |
type = node.getAttribute ("type") |
params['width'] = int(node.getAttribute ("width")) |
width = node.getAttribute ("width") |
if (width == ''): params['width'] = 1 |
else : params['width'] = int(width) |
params['default'] = node.getAttribute ("default") |
params['int_value'] = node.getAttribute ("int_value") |
|
52,11 → 101,40
# if anode.nodeType = anode.ATTRIBUTE_NODE: |
# params[anode.nodeName] = anode.nodeValue |
|
print "Reg:",params['name'], " width:",params['width'] |
fld_nodes = node.getElementsByTagName ("field") |
fld_list = [] |
cum_width = 0 |
cum_default = 0L |
if (len(fld_nodes) != 0): |
for fld in fld_nodes: |
wstr = fld.getAttribute ("width") |
if wstr == '': |
width = 1 |
else: |
width = int(wstr) |
fld_list.append (reglib.net('wire',fld.getAttribute("name"),width)) |
|
default = fld.getAttribute ("default") |
if default == '': |
default = 0 |
else: |
default = long(reglib.number (default)) |
cum_default = cum_default | (default << cum_width) |
print "Fld: %20s CD: %x CW: %d D: %x" % (fld.getAttribute("name"),cum_default, cum_width, default) |
cum_width += width |
|
params['width'] = cum_width |
params['default'] = cum_default |
fld_list.reverse() |
else: |
if params['default'] == '': params['default'] = 0 |
else: params['default'] = reglib.number (params['default']) |
|
if type == '': type = 'config' |
if params['default'] == '': params['default'] = 0 |
else: params['default'] = reglib.number (params['default']) |
|
rg.add_register (type, params) |
rg.registers[-1].fields = fld_list |
|
def create_verilog (top_node): |
rg = create_reg_group (top_node) |
72,6 → 150,27
fh.write (rg.verilog()) |
fh.close() |
|
create_map (rg) |
create_vh (rg) |
|
def create_vh (rg): |
fname = rg.name + ".vh" |
fh = open (fname, 'w') |
for r in rg.registers: |
fh.write ("`define %s 16'h%04x\n" % (string.upper(r.name), rg.base_addr+r.offset)) |
fh.close() |
|
def create_map (rg): |
fname = rg.name + ".h" |
fh = open (fname, 'w') |
|
for r in rg.registers: |
fh.write ("#define %s 0x%x\n" % (string.upper(r.name),r.offset)) |
|
#for r in rg.registers: |
# fh.write ("sfr at 0x%02x %s;\n" % (r.offset, r.name)) |
fh.close() |
|
def parse_file (filename): |
rdoc = xml.dom.minidom.parse (filename) |
blk_list = rdoc.getElementsByTagName ("tv_registers") |
79,8 → 178,20
for blk in blk_list: |
create_verilog (blk) |
|
dec_list = rdoc.getElementsByTagName ("it_decoder") |
|
for dec in dec_list: |
create_decoder_verilog (dec) |
|
rdoc.unlink() |
|
def check_version(): |
version = float (sys.version[0:3]) |
if (version < 2.3): |
print "rgen requires at least Python 2.3 to function correctly" |
sys.exit (1) |
|
check_version() |
if (len (sys.argv) > 1): |
parse_file (sys.argv[1]) |
else: |
/scripts/reglib.py
41,6 → 41,15
print "ERROR: number conversion of %s failed" % str |
return 0 |
|
def int2bin (n): |
bStr = '' |
if (n < 0): raise ValueError, "must be positive integer" |
if (n == 0): return '0' |
while (n > 0): |
bStr = str (n%2) + bStr |
n = n >> 1 |
return bStr |
|
def comb_block (statements): |
result = 'always @*\n' |
result += ' begin\n' |
50,7 → 59,7
return result |
|
def seq_block (clock, statements): |
result = 'always @(posedge ' + clock + ')\n' |
result = 'always @(posedge ' + clock + ' or negedge reset_n)\n' |
result += ' begin\n' |
for s in statements: |
result += ' ' + s + '\n' |
80,7 → 89,137
return self.direction + ' ' + self.name + ';' |
else: |
return "%s [%d:0] %s;" % (self.direction, self.width-1, self.name) |
|
class decoder_range: |
def __init__ (self, name, base, bits): |
self.name = name |
self.base = base |
self.bits = bits |
|
def check_range(self): |
mask = (1 << self.bits) - 1 |
if (self.base & mask): |
return 1 |
else: return 0 |
|
def get_base_addr(self): |
return self.base |
|
class decoder_group: |
def __init__ (self, mem_mapped=0): |
self.addr_size = 16 |
self.data_size = 8 |
self.name = '' |
self.ranges = [] |
self.ports = [port ('input', 'clk'), port('input','reset_n')] |
self.nets = [] |
|
self.blocks = [] |
|
def build (self): |
self.ports.append (port ('input', 'cfgi_irdy')) |
self.ports.append (port ('output', 'cfgi_trdy')) |
self.ports.append (port ('input', 'cfgi_write')) |
self.ports.append (port ('input', 'cfgi_addr', self.addr_size)) |
self.ports.append (port ('input', 'cfgi_wr_data', self.data_size)) |
self.ports.append (port ('output', 'cfgo_wr_data', self.data_size)) |
self.ports.append (port ('output', 'cfgi_rd_data', self.data_size)) |
self.ports.append (port ('output', 'cfgo_addr', self.addr_size)) |
self.ports.append (port ('output', 'cfgo_write')) |
self.nets.append (net('reg','cfgi_rd_data',self.data_size)) |
self.nets.append (net('reg','nxt_rd_data',self.data_size)) |
self.nets.append (net('reg', 'nxt_cfgi_trdy')) |
self.nets.append (net('reg', 'irdy_out')) |
self.nets.append (net('reg', 'trdy_out')) |
self.nets.append (net('reg', 'cfgo_wr_data', self.data_size)) |
self.nets.append (net('reg', 'cfgo_addr', self.addr_size)) |
self.nets.append (net ('reg', 'cfgo_write')) |
self.nets.append (net ('reg', 'cfgi_trdy')) |
self.blocks.append ( """ |
always @(posedge clk or negedge reset_n) |
begin |
if (~reset_n) |
begin |
irdy_out <= #1 0; |
cfgo_wr_data <= #1 0; |
cfgo_addr <= #1 0; |
cfgo_write <= #1 0; |
cfgi_trdy <= #1 0; |
end |
else |
begin |
irdy_out <= #1 (irdy_out) ? !trdy_out : cfgi_irdy & ~cfgi_trdy; |
cfgi_trdy <= #1 irdy_out & trdy_out; |
|
if (cfgi_irdy & !irdy_out) |
begin |
cfgo_wr_data <= #1 cfgi_wr_data; |
cfgo_addr <= #1 cfgi_addr; |
cfgo_write <= #1 cfgi_write; |
end |
if (trdy_out & !cfgo_write) |
cfgi_rd_data <= #1 nxt_rd_data; |
end // else: !if(reset) |
end // always @ (posedge clk)\n""") |
|
addr_mux = ["casez (cfgo_addr)\n"] |
for r in self.ranges: |
self.ports.append (port ('output', r.name + "_irdy")) |
self.ports.append (port ('input', r.name + "_trdy")) |
self.ports.append (port ('input', r.name + "_rd_data", self.data_size)) |
self.nets.append (net('reg', r.name + "_irdy")) |
addr_mux.insert(0, "%s_irdy = 0;" % r.name) |
base_addr = int2bin (r.base) |
#for b in range(-r.bits,0): |
# base_addr[b] = 'z' |
fill = self.addr_size - len(base_addr) |
if (fill > 0): |
base_addr = '0' * fill + base_addr |
base_addr = base_addr[:-r.bits] + 'z'*r.bits |
addr_mux.append ("%d'b%s :" % (self.addr_size, base_addr)) |
addr_mux.append ("begin") |
addr_mux.append ("%s_irdy = irdy_out;" % r.name) |
addr_mux.append ("trdy_out = %s_trdy;" % r.name) |
addr_mux.append ("nxt_rd_data = %s_rd_data;" % r.name) |
addr_mux.append ("end") |
|
addr_mux.append(""" |
default : |
begin |
trdy_out = 1'b1; |
nxt_rd_data = 0; |
end |
endcase\n""") |
|
self.blocks.append (comb_block(addr_mux)) |
|
|
def verilog (self): |
self.build() |
result = 'module ' + self.name + ' (\n' |
result += string.join (map (lambda x: x.name, self.ports), ',') |
result += ');\n' |
|
# print port list |
for p in self.ports: |
result += p.declaration() + '\n' |
|
# print net list |
for n in self.nets: |
result += n.declaration() + '\n' |
|
# create all blocks in block list |
for b in self.blocks: |
result += b |
|
result += 'endmodule\n' |
return result |
|
|
|
def add_range (self, r): |
self.ranges.append (r) |
|
class register_group: |
def __init__ (self, mem_mapped=0): |
self.base_addr = 0 |
87,32 → 226,60
self.addr_size = 16 |
self.data_size = 8 |
self.name = '' |
self.local_width = 1 |
self.local_width = 1 # number of address bits consumed |
self.registers = [] |
self.ports = [port ('input', 'clk'), port('input','reset')] |
self.ports = [port ('input', 'clk'), port('input','reset_n')] |
self.nets = [] |
self.interrupts = 0 |
if (mem_mapped): |
self.req_pin = 'mreq_n' |
else: |
self.req_pin = 'iorq_n' |
self.tv80_intf() |
self.interrupts = 0 # if interrupt registers present |
self.user = 0 # if user-defined registers present |
self.blocks = [] |
self.registered_read = 0 |
self.hold_regs = 0 |
self.hold_inputs = [] |
|
def tv80_intf (self): |
self.ports.append (port ('input', 'addr', self.addr_size)) |
self.ports.append (port ('input', 'wr_data', self.data_size)) |
self.ports.append (port ('output', 'rd_data', self.data_size)) |
self.ports.append (port ('output', 'doe')) |
self.ports.append (port ('input','rd_n')) |
self.ports.append (port ('input', 'wr_n')) |
self.ports.append (port ('input', self.req_pin)) |
self.nets.append (net('reg','rd_data',self.data_size)) |
self.nets.append (net('reg','block_select')) |
self.nets.append (net('reg','doe')) |
def top_intf (self): |
self.ports.append (port ('input', 'rf_irdy')) |
self.ports.append (port ('output', 'rf_trdy')) |
self.ports.append (port ('input', 'rf_write')) |
self.ports.append (port ('input', 'rf_addr', self.addr_size)) |
self.ports.append (port ('input', 'rf_wr_data', self.data_size)) |
self.ports.append (port ('output', 'rf_rd_data', self.data_size)) |
self.nets.append (net('reg','rf_rd_data',self.data_size)) |
self.nets.append (net('reg', 'nxt_rf_trdy')) |
if (self.registered_read): |
self.nets.append (net('reg','nxt_rf_rd_data',self.data_size)) |
for i in range(0,self.hold_regs): |
self.nets.append (net('reg',"xxhold_%d" % i,self.data_size)) |
self.nets.append (net('reg',"nxt_xxhold_%d" % i,self.data_size)) |
self.nets.append (net('reg', 'rf_trdy')) |
|
def build_load_mux (self): |
for i in range(0,self.hold_regs): |
nn = "nxt_xxhold_%d" % i |
txt = [] |
for hi,nregs in self.hold_inputs: |
high = (i+1) * self.data_size - 1 |
low = i* self.data_size |
if (i < nregs): |
txt.append ("if (%s_rd_stb) %s = %s_in[%d:%d];" % (hi, nn, hi, high, low)) |
txt.append ("else if (%s_%d_wr_sel) %s = rf_wr_data; else " % (hi, i, nn)) |
txt.append("%s = xxhold_%d;" % (nn, i)) |
self.blocks.append (comb_block(txt)) |
|
# create a hook for post-processing to be done after all data has been |
# added to the object. |
def post (self): |
self.top_intf() |
for reg in self.registers: |
self.ports.extend (reg.io()) |
self.nets.extend (reg.nets()) |
#self.local_width = int(math.ceil (log2 (len (self.registers)))) |
self.local_width = self.addr_size; |
rnum = 0 |
for r in self.registers: |
r.offset = rnum |
rnum += 1 |
self.build_load_mux() |
if (self.interrupts): |
self.int_ports() |
|
122,29 → 289,54
def int_ports (self): |
self.ports.append (port ('output','int_n')) |
self.nets.append (net ('reg','int_n')) |
self.nets.append (net ('reg','int_vec',self.data_size)) |
#self.nets.append (net ('reg','int_vec',self.data_size)) |
|
def int_logic (self): |
statements = [] |
int_nets = [] |
for r in self.registers: |
if r.interrupt: int_nets.append (r.name + "_int") |
statements.append ("int_n = ~(" + string.join (int_nets, ' | ') + ");") |
return comb_block (statements) |
self.blocks.append (comb_block (["int_n = ~(" + string.join (int_nets, ' | ') + ");"])) |
|
def wait_logic (self): |
wait_nets = [] |
for r in self.registers: |
if r.type() == 'user': |
wait_nets.append (r.name + "_wait_n") |
elif r.type() == 'ext_load': |
if r.eindex == 0: |
wait_nets.append (r.name + "_wait_n") |
if (len(wait_nets) > 0): |
self.blocks.append (comb_block (["if (rf_trdy) nxt_rf_trdy = 0;", |
"else if (rf_irdy) nxt_rf_trdy = " + ' & '.join (wait_nets) + ";", |
"else nxt_rf_trdy = 0;"])) |
else: |
self.blocks.append (comb_block (["if (rf_trdy) nxt_rf_trdy = 0;", |
"else if (rf_irdy) nxt_rf_trdy = 1;", |
"else nxt_rf_trdy = 0;"])) |
self.blocks.append (seq_block ("clk", ["if (~reset_n) rf_trdy <= #1 0;", |
"else rf_trdy <= #1 nxt_rf_trdy;"])) |
#if (len(wait_nets) > 0): |
# self.blocks.append (comb_block (["wait_n = " + string.join (wait_nets, ' & ') + ";"])) |
|
if (self.registered_read): |
self.blocks.append (seq_block ("clk", ["if (~reset_n) rf_rd_data <= #1 0;", "else if (nxt_rf_trdy) rf_rd_data <= #1 nxt_rf_rd_data;"])) |
for i in range (0,self.hold_regs): |
self.blocks.append (seq_block ("clk", ["if (~reset_n) xxhold_%d <= 0;"%i,"else xxhold_%d <= nxt_xxhold_%d;" % (i, i)])) |
|
|
def global_logic (self): |
# create select pin for this block |
statements = ["block_select = (addr[%d:%d] == %d) & !%s;" % (self.addr_size-1,self.local_width,self.base_addr >> self.local_width, self.req_pin)] |
statements = [] |
|
# create read and write selects for each register |
for r in self.registers: |
slogic = "block_select & (addr[%d:%d] == %d) & !rd_n" % (self.local_width-1,0,r.offset) |
slogic = "(rf_addr[%d:%d] == %d) & rf_irdy & !rf_write" % (self.local_width-1,0,r.offset) |
#if r.interrupt: |
# slogic = "%s_int | (%s)" % (r.name, slogic) |
s = "%s_rd_sel = %s;" % (r.name,slogic) |
statements.append (s) |
if r.write_cap(): |
s = "%s_wr_sel = block_select & (addr[%d:%d] == %d) & !wr_n;" % (r.name,self.local_width-1,0,r.offset) |
s = "%s_wr_sel = (rf_addr[%d:%d] == %d) & rf_irdy & rf_write;\n" % (r.name,self.local_width-1,0,r.offset) |
statements.append (s) |
|
return comb_block (statements) |
153,30 → 345,22
s = '' |
sments = [] |
rd_sel_list = [] |
# Old code for simple tri-state interface |
#for r in self.registers: |
# s += "assign rd_data = (%s_rd_sel) ? %s : %d'bz;\n" % (r.name, r.name, self.data_size) |
|
# create interrupt address mux |
if (self.interrupts): |
sments.append ("case (1'b1)") |
for r in self.registers: |
if r.interrupt: |
sments.append (" %s_int : int_vec = %d;" % (r.name, r.int_value)) |
sments.append (" default : int_vec = %d'bx;" % self.data_size) |
sments.append ("endcase") |
|
# create data-output mux |
sments.append ("case (1'b1)") |
if (self.registered_read): |
rd_target = "nxt_rf_rd_data" |
else: |
rd_target = "rf_rd_data" |
for r in self.registers: |
sments.append (" %s_rd_sel : rd_data = %s;" % (r.name, r.name)) |
sments.append (" %s_rd_sel : %s = %s;" % (r.name, rd_target, r.name)) |
rd_sel_list.append (r.name + "_rd_sel") |
if (self.interrupts): |
sments.append (" default : rd_data = int_vec;") |
else: sments.append (" default : rd_data = %d'bx;" % self.data_size) |
#if (self.interrupts): |
# sments.append (" default : rd_data = int_vec;") |
sments.append (" default : %s = %d'b0;" % (rd_target, self.data_size)) |
sments.append ("endcase") |
|
sments.append ("doe = %s;" % string.join (rd_sel_list, ' | ')) |
#sments.append ("doe = %s;" % string.join (rd_sel_list, ' | ')) |
|
return comb_block (sments) |
|
199,7 → 383,12
# create global logic |
result += self.global_logic() |
result += self.read_mux() |
if (self.interrupts > 0): result += self.int_logic() |
if (self.interrupts > 0): self.int_logic() |
self.wait_logic() |
|
# create all blocks in block list |
for b in self.blocks: |
result += b |
|
# print function blocks |
for r in self.registers: |
208,6 → 397,16
result += 'endmodule\n' |
return result |
|
# calculate number of holding registers required and update |
# hold_regs internal property |
def calc_hold (self, width): |
hregs = width / self.data_size |
if (width % self.data_size) != 0: |
hregs += 1 |
if (hregs > self.hold_regs): |
self.hold_regs = hregs |
return hregs |
|
def add_register (self, type, params): |
#def add_register (self, name, type, width): |
if (type == 'status'): |
214,9 → 413,9
self.add (status_reg (params['name'],params['width'])) |
elif (type == 'config'): |
self.add (config_reg (params['name'],params['width'],params['default'])) |
elif (type == 'int_fixed'): |
elif (type == 'int_msk'): |
r2 = config_reg (params['name'] + "_msk",params['width'],params['default']) |
r1 = int_fixed_reg (params['name'],r2,number(params['int_value']),params['width']) |
r1 = int_msk_reg (params['name'],r2,params['width']) |
self.add (r1) |
self.add (r2) |
self.interrupts += 1 |
226,20 → 425,31
self.add (read_stb_reg (params['name'],params['width'])) |
elif (type == 'write_stb'): |
self.add (write_stb_reg (params['name'],params['width'],params['default'])) |
elif (type == 'hw_load'): |
self.add (hw_load_reg (params['name'],params['width'])) |
elif (type == 'user'): |
self.user = 1 |
self.add (user_reg (params['name'],params['width'])) |
elif (type == 'ext_load'): |
width = params['width'] |
regs = self.calc_hold (width) |
print "ext_load %s, splitting into %d regs" % (params['name'],regs) |
for i in range(0,regs): |
last = (i == (regs-1)) |
self.add (ext_load_reg(params['name'],self.data_size,i,params['width'],last)) |
self.hold_inputs.append ( (params['name'], regs) ) |
elif (type == 'count'): |
self.add (count_reg (params['name'],params['width'])) |
else: |
print "Unknown register type",type |
|
def add (self, reg): |
self.registers.append (reg) |
self.ports.extend (reg.io()) |
self.nets.extend (reg.nets()) |
self.local_width = int(math.ceil (log2 (len (self.registers)))) |
rnum = 0 |
for r in self.registers: |
r.offset = rnum |
rnum += 1 |
#self.ports.extend (reg.io()) |
#self.nets.extend (reg.nets()) |
#self.local_width = int(math.ceil (log2 (len (self.registers)))) |
#rnum = 0 |
#for r in self.registers: |
# r.offset = rnum |
# rnum += 1 |
|
class basic_register: |
def __init__ (self, name='', width=0): |
251,6 → 461,9
def verilog_body (self): |
pass |
|
def type (self): |
return 'basic' |
|
def io (self): |
return [] |
|
261,14 → 474,17
return 0 |
|
def id_comment (self): |
return "// register: %s\n" % self.name |
return "// %s: %s\n" % (self.type(), self.name) |
|
class status_reg (basic_register): |
def __init__ (self, name='', width=0): |
basic_register.__init__(self, name, width) |
|
def type (self): |
return 'status' |
|
def verilog_body (self): |
return '' |
return self.id_comment() |
|
def io (self): |
return [port('input', self.name, self.width)] |
276,22 → 492,110
def nets (self): |
return [ net('reg', self.name + '_rd_sel')] |
|
class ext_load_reg (basic_register): |
def __init__ (self, name='', width=0, eindex=0, twidth=0, last=0): |
basic_register.__init__(self, name+"_%d" % eindex, width) |
self.fullname = name |
self.eindex = eindex |
self.twidth = twidth |
self.last = last |
print "Adding %s eindex %d" % (name, eindex) |
|
def type (self): return "ext_load" |
|
def write_cap (self): return 1 |
|
def verilog_body (self): |
print "Building %s eindex %d" % (self.name, self.eindex) |
|
txt = "" |
low = self.eindex * self.width |
high = (self.eindex + 1) * self.width - 1 |
txt += "assign %s = xxhold_%d;\n" % (self.name, self.eindex) |
txt += "assign %s_out[%d:%d] = xxhold_%d;\n" % (self.fullname, high, low, self.eindex) |
if (self.eindex == 0): |
#txt += "assign %s_rd_stb = %s_rd_sel & !rf_trdy;\n" % (self.fullname,self.name) |
sm = state_machine ("sm_" + self.name) |
sm.add_state ('idle') |
sm.add_state ('rd_req') |
sm.add_state ('done') |
|
sm.add_trans ('idle','rd_req',self.name+"_rd_sel", self.name+"_wait_n = 0") |
sm.add_trans ('rd_req','done',"1'b1") |
sm.add_moore ('rd_req',self.name+"_wait_n = 1'b0") |
sm.add_moore ('rd_req',self.fullname+"_rd_stb = 1'b1") |
|
sm.add_trans ('done','idle',"~%s_rd_sel" % self.name) |
|
sm.add_default (self.fullname+"_rd_stb", "1'b0") |
sm.add_default (self.name+"_wait_n", "1'b1") |
txt += sm.verilog() |
|
if (self.last): |
txt += seq_block ("clk", ["if (~reset_n) %s_wr_stb <= 1'b0;" % self.fullname, |
"else %s_wr_stb <= %s_%d_wr_sel;" % (self.fullname,self.fullname,self.eindex)]) |
return txt |
|
def nets (self): |
nets = [net('reg', self.name + '_rd_sel'), |
net('reg', self.name + '_wr_sel'), |
net('wire', self.name, self.width)] |
if (self.eindex == 0): |
nets.append (net('reg', self.name + "_wait_n")) |
nets.append (net('reg',"sm_%s_state" % self.name, 2)) |
nets.append (net('reg',"nxt_sm_%s_state" % self.name, 2)) |
if (self.last): |
nets.append (net('reg', self.fullname + '_rd_stb')) |
nets.append (net('reg', self.fullname + '_wr_stb')) |
return nets |
|
def io (self): |
# ports are all tied to the 0 eindex register |
plist = [] |
if (self.eindex == 0): |
plist.append (port('input', self.fullname+"_in", self.twidth)) |
plist.append (port('output', self.fullname+"_out", self.twidth)) |
plist.append (port('output', self.fullname+"_rd_stb", 1)) |
plist.append (port('output', self.fullname+"_wr_stb", 1)) |
return plist |
|
|
class config_reg (basic_register): |
def __init__ (self, name='', width=0, default=0): |
basic_register.__init__(self, name, width) |
self.default = default |
self.fields = [] |
|
def verilog_body (self): |
statements = ["if (reset) %s <= %d;" % (self.name, self.default), |
"else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data') |
] |
return self.id_comment() + seq_block ('clk', statements) |
vstr = self.id_comment() |
statements = ["if (%s_wr_sel) nxt_%s = %s;" % (self.name, self.name, 'rf_wr_data'), |
"else nxt_%s = %s;" % tuple([self.name] * 2)] |
vstr += comb_block (statements) |
statements = ["if (~reset_n) %s <= #1 %d'h%x;" % (self.name, self.width, self.default), |
"else %s <= #1 nxt_%s;" % tuple([self.name] * 2)] |
|
vstr += seq_block ('clk', statements) |
if (len(self.fields) != 0): |
vstr += "assign {" |
vstr += ','.join (map(lambda(x):x.name,self.fields)) |
vstr += "} = %s;\n" % self.name |
return vstr |
|
def type (self): |
return 'config' |
|
def io (self): |
return [ port('output',self.name, self.width) ] |
if (len(self.fields) == 0): |
return [ port('output',self.name, self.width) ] |
else: |
plist = [] |
for fld in self.fields: |
plist.append (port ('output', fld.name, fld.width)) |
return plist |
|
def nets (self): |
return [ net('reg', self.name, self.width), |
net('reg', "nxt_"+self.name, self.width), |
net('reg', self.name + '_rd_sel'), |
net('reg', self.name + '_wr_sel')] |
|
298,48 → 602,52
def write_cap (self): |
return 1 |
|
class hw_load_reg (config_reg): |
class count_reg (config_reg): |
def __init__ (self, name='', width=0, default=0): |
basic_register.__init__(self, name, width) |
config_reg.__init__(self, name, width) |
self.default = default |
|
def verilog_body (self): |
statements = ["if (reset) %s <= %d;" % (self.name, self.default), |
"else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'), |
"else if (%s_load) %s <= %s_wrdata;" % (self.name,self.name,self.name) |
txt = self.id_comment() |
alist = (self.name, self.name, self.width, self.name, self.name) |
statements = [ |
"if (%s_wr_sel) nxt_%s = %s;" % (self.name, self.name, 'rf_wr_data'), |
"else if (%s_inc && (%s != {%d{1'b1}})) nxt_%s = %s + 1;" % alist, |
"else nxt_%s = %s;" % (self.name,self.name) |
] |
return self.id_comment() + seq_block ('clk', statements) |
|
txt += comb_block (statements) |
statements = ["if (~reset_n) %s <= #1 %d;" % (self.name, self.default), |
"else %s <= #1 nxt_%s;" % (self.name, self.name) |
] |
txt += seq_block ('clk', statements) |
return txt |
|
def io (self): |
return [ port('input', self.name+'_wrdata', self.width), |
port('input', self.name+'_load', 1), |
port('output',self.name, self.width) ] |
return [ port('input',self.name + "_inc", 1) ] |
|
def nets (self): |
return [ net('reg', self.name, self.width), |
net('reg', self.name + '_rd_sel'), |
net('reg', self.name + '_wr_sel')] |
|
def write_cap (self): |
return 1 |
|
|
class int_fixed_reg (basic_register): |
def __init__ (self, name, mask_reg, int_value, width=0): |
class int_msk_reg (basic_register): |
def __init__ (self, name, mask_reg, width=0): |
basic_register.__init__(self, name, width) |
self.mask_reg = mask_reg |
self.interrupt = 1 |
self.int_value = int_value |
|
def verilog_body (self): |
statements = ["if (reset) %s <= %d;" % (self.name, 0), |
"else %s <= (%s_set | %s) & ~( {%d{%s}} & %s);" % |
(self.name, self.name, self.name, self.width, self.name + '_wr_sel', 'wr_data'), |
"if (reset) %s_int <= 0;" % self.name, |
"else %s_int <= |(%s & ~%s);" % (self.name, self.name, self.mask_reg.name) |
text = self.id_comment() |
statements = ["nxt_%s = (%s_set | %s) & ~( {%d{%s}} & %s);" % (self.name, self.name, self.name, self.width, self.name + '_wr_sel', 'rf_wr_data')] |
statements += ["nxt_%s_int = |(%s & ~%s);" % (self.name, self.name, self.mask_reg.name)] |
text += comb_block (statements) |
statements = ["if (~reset_n) %s <= #1 %d;" % (self.name, 0), |
"else %s <= #1 nxt_%s;" % (self.name, self.name)] |
text += seq_block ('clk', statements) |
statements = ["if (~reset_n) %s_int <= #1 0;" % self.name, |
"else %s_int <= nxt_%s_int;" % (self.name, self.name) |
] |
return self.id_comment() + seq_block ('clk', statements) |
text += seq_block ('clk', statements) |
return text |
|
def type (self): |
return 'int_msk' |
|
def io (self): |
return [ port('input',self.name+"_set", self.width) ] |
|
346,36 → 654,51
def nets (self): |
return [ net('reg', self.name + '_rd_sel'), |
net('reg', self.name, self.width), |
net('reg', "nxt_"+self.name, self.width), |
net('reg', self.name + '_wr_sel'), |
net('reg', 'nxt_'+self.name + '_int'), |
net('reg', self.name + '_int')] |
|
def write_cap (self): |
return 1 |
|
class soft_set_reg (basic_register): |
class soft_set_reg (config_reg): |
def __init__ (self, name='', width=0, default=0): |
basic_register.__init__(self, name, width) |
self.default = default |
|
def verilog_body (self): |
statements = ["if (reset) %s <= %d;" % (self.name, self.default), |
"else %s <= ( ({%d{%s}} & %s) | %s) & ~(%s);" % |
(self.name, self.width, self.name+'_wr_sel', 'wr_data', |
txt = self.id_comment() |
statements = [ |
"nxt_%s = ( ({%d{%s}} & %s) | %s) & ~(%s);" % |
(self.name, self.width, self.name+'_wr_sel', 'rf_wr_data', |
self.name, self.name + '_clr') |
] |
return self.id_comment() + seq_block ('clk', statements) |
txt += comb_block (statements) |
statements = ["if (~reset_n) %s <= #1 %d;" % (self.name, self.default), |
"else %s <= #1 nxt_%s;" % (self.name, self.name) |
] |
txt += seq_block ('clk', statements) |
if (len(self.fields) != 0): |
txt += "assign {" |
txt += ','.join (map(lambda(x):x.name,self.fields)) |
txt += "} = %s;\n" % self.name |
return txt |
|
def type (self): |
return 'soft_set' |
|
def io (self): |
return [ port('output',self.name, self.width), |
port ('input',self.name+"_clr", self.width)] |
return config_reg.io(self) + [port ('input',self.name+"_clr", self.width)] |
|
def nets (self): |
return [ net('reg', self.name, self.width), |
net('reg', self.name + '_rd_sel'), |
net('reg', self.name + '_wr_sel')] |
#def nets (self): |
# return [ net('reg', self.name, self.width), |
# net('reg', "nxt_"+self.name, self.width), |
# net('reg', self.name + '_rd_sel'), |
# net('reg', self.name + '_wr_sel')] |
|
def write_cap (self): |
return 1 |
#def write_cap (self): |
# return 1 |
|
class write_stb_reg (config_reg): |
def __init__ (self, name='', width=0, default=0): |
382,14 → 705,30
config_reg.__init__(self, name, width, default) |
|
def verilog_body (self): |
statements = ["if (reset) %s <= %d;" % (self.name, self.default), |
"else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'), |
"if (reset) %s_stb <= 0;" % (self.name), |
"else if (%s_wr_sel) %s_stb <= 1;" % (self.name, self.name), |
"else %s_stb <= 0;" % (self.name) |
txt = self.id_comment() |
statements = [ |
"if (%s_wr_sel) nxt_%s = %s;" % (self.name, self.name, 'rf_wr_data'), |
"else nxt_%s = %s;" % (self.name, self.name)] |
txt += comb_block (statements) |
statements = ["if (~reset_n) %s <= #1 %d;" % (self.name, self.default), |
"else %s <= #1 nxt_%s;" % (self.name, self.name)] |
txt += seq_block('clk',statements) |
statements = [ |
"if (~reset_n) %s_stb <= #1 0;" % (self.name), |
"else %s_stb <= #1 %s_wr_sel & rf_trdy;" % (self.name, self.name), |
] |
return seq_block ('clk', statements) |
txt += seq_block ('clk', statements) |
|
if (len(self.fields) != 0): |
txt += "assign {" |
txt += ','.join (map(lambda(x):x.name,self.fields)) |
txt += "} = %s;\n" % self.name |
|
return txt+seq_block ('clk', statements) |
|
def type (self): |
return 'write_stb' |
|
def io (self): |
io_list = config_reg.io (self) |
io_list.append ( port('output',self.name+"_stb") ) |
406,12 → 745,14
|
def verilog_body (self): |
statements = [ |
"if (reset) %s_stb <= 0;" % (self.name), |
"else if (%s_rd_sel) %s_stb <= 1;" % (self.name, self.name), |
"else %s_stb <= 0;" % (self.name) |
"if (~reset_n) %s_stb <= #1 0;" % (self.name), |
"else %s_stb <= #1 %s_rd_sel & rf_trdy;" % (self.name, self.name), |
] |
return self.id_comment() + seq_block ('clk', statements) |
|
def type (self): |
return 'read_stb' |
|
def io (self): |
io_list = status_reg.io (self) |
io_list.append (port('output',self.name+"_stb")) |
421,3 → 762,140
net_list = status_reg.nets(self) |
net_list.append (net('reg',self.name + '_stb')) |
return net_list |
|
class state_machine: |
def __init__ (self, name='', clk="clk", reset="reset_n"): |
self.name = name |
self.states = {} |
self.trans = [] |
self.clk = clk |
self.reset = reset |
self.idle = "" |
self.defaults = [] |
|
def add_state (self, name): |
self.states[name] = [] |
if (self.idle == ""): |
self.idle = name |
|
def add_trans (self, st_from, st_to, cond, asrt=''): |
self.states[st_from].append ( (st_to, cond, asrt) ) |
|
def add_moore (self, st_name, asrt): |
self.states[st_name].append ( (st_name, '1', asrt) ) |
|
def add_default (self, signal, value): |
self.defaults.append ( (signal, value) ) |
|
def verilog (self): |
code = "// state machine %s\n" % self.name |
|
# create state names |
snum = 0 |
for st in self.states.keys(): |
code += "parameter st_%s_%s = %d;\n" % (self.name, st, snum) |
snum += 1 |
|
# create combinatorial block |
cblk = [] |
for d in self.defaults: |
cblk.append ( "%s = %s;" % d) |
cblk.append ("%s = %s;" % ("nxt_" + self.name + "_state", self.name + "_state")) |
cblk.append ("case (%s)" % (self.name + "_state")) |
for st in self.states.keys(): |
cblk.append ( "st_%s_%s : " % (self.name, st)) |
cblk.append ( " begin") |
first = 1 |
moore = [] |
for c in self.states[st]: |
if (c[0] == st) and (c[1] == "1"): |
moore.append (c[2]) |
else: |
if (not first): statement = " else if" |
else: |
statement = " if" |
first = 0 |
cblk.append ( "%s (%s)" % (statement, c[1])) |
cblk.append (" begin") |
if (c[0] != st): |
cblk.append ( " nxt_%s_state = st_%s_%s;" % (self.name, self.name, c[0])) |
if (c[2] != ""): |
cblk.append ( " " + c[2] + ";") |
cblk.append ( " end") |
for m in moore: |
cblk.append (" %s;" % m) |
cblk.append (" end") |
cblk.append ( "endcase") |
code += comb_block (cblk) |
|
# create sequential block |
cblk = [] |
cblk.append ("if(~%s)" % self.reset) |
cblk.append ("%s_state <= #1 st_%s_%s;" % (self.name, self.name, self.idle)) |
cblk.append ("else") |
cblk.append ("%s_state <= #1 nxt_%s_state;" % (self.name, self.name)) |
code += seq_block (self.clk, cblk) |
return code |
|
class user_reg (basic_register): |
def __init__ (self, name='', width=0): |
basic_register.__init__(self, name, width) |
|
def io (self): |
io_list = [] |
io_list.append (port('output',self.name+"_wr_stb")) |
io_list.append (port('output',self.name+"_rd_stb")) |
io_list.append (port('output',self.name+"_wr_data", self.width)) |
io_list.append (port('input',self.name+"_rd_data",self.width)) |
io_list.append (port('input',self.name+"_rd_ack")) |
io_list.append (port('input',self.name+"_wr_ack")) |
return io_list |
|
def type (self): |
return 'user' |
|
def nets (self): |
net_list = [] |
net_list.append (net('reg',self.name+"_rd_sel")) |
net_list.append (net('reg',self.name+"_wr_sel")) |
net_list.append (net('reg',self.name+"_rd_stb")) |
net_list.append (net('reg',self.name+"_wr_stb")) |
net_list.append (net('reg',self.name+"_wait_n")) |
net_list.append (net('reg',self.name,self.width)) |
net_list.append (net('reg',self.name+"_wr_data",self.width)) |
net_list.append (net('reg',"sm_%s_state" % self.name, 2)) |
net_list.append (net('reg',"nxt_sm_%s_state" % self.name, 2)) |
return net_list |
|
def write_cap (self): |
return 1 |
|
def verilog_body (self): |
sm = state_machine ("sm_" + self.name) |
sm.add_state ('idle') |
sm.add_state ('rd_req') |
sm.add_state ('wr_req') |
sm.add_state ('w_clear') |
#sm.add_state ('rd_ack') |
#sm.add_state ('wr_ack') |
sm.add_trans ('idle','rd_req',self.name+"_rd_sel", self.name+"_wait_n = 0") |
sm.add_trans ('idle','wr_req',self.name+"_wr_sel", self.name+"_wait_n = 0") |
sm.add_trans ('rd_req', 'w_clear', self.name+"_rd_ack", "") |
#sm.add_trans ('rd_req', 'rd_ack', '1','') |
sm.add_trans ('rd_req', 'rd_req', "!"+self.name+"_rd_ack", self.name+"_wait_n = 0") |
sm.add_moore ('rd_req', self.name+"_rd_stb = 1") |
sm.add_moore ('wr_req', self.name+"_wr_stb = 1") |
sm.add_trans ('wr_req', 'w_clear', self.name+"_wr_ack", "") |
sm.add_trans ('wr_req', 'wr_req', "!"+self.name+"_wr_ack", self.name+"_wait_n = 0") |
|
# added w_clear to avoid duplicate requests on interface |
sm.add_trans ('w_clear', 'idle', "~(%s_rd_sel | %s_wr_sel)" % (self.name,self.name), "") |
|
sm.add_default (self.name+"_rd_stb", "0") |
sm.add_default (self.name+"_wr_stb", "0") |
sm.add_default (self.name+"_wait_n", "1") |
|
comb = comb_block (["%s_wr_data = rf_wr_data;" % self.name, |
"%s = %s_rd_data;" % (self.name, self.name)]) |
|
return sm.verilog() + comb |