
<?xml 
version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="https://63f09.systella.fr/spip.php?page=backend.xslt" ?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom"
>

<channel xml:lang="en">
	<title>63F09</title>
	<link>https://63F09.systella.fr/</link>
	<description></description>
	<language>en</language>
	<generator>SPIP - www.spip.net</generator>
	<atom:link href="https://63f09.systella.fr/spip.php?id_rubrique=2&amp;page=backend" rel="self" type="application/rss+xml" />

	<image>
		<title>63F09</title>
		<url>https://63f09.systella.fr/local/cache-vignettes/L110xH56/kl_motorola_mc6809-0d844.jpg?1788338251</url>
		<link>https://63F09.systella.fr/</link>
		<height>56</height>
		<width>110</width>
	</image>



<item xml:lang="en">
		<title>BAC 63F81</title>
		<link>https://63f09.systella.fr/soc-63f09/peripherals/article/bac-63f81</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/peripherals/article/bac-63f81</guid>
		<dc:date>2024-08-23T17:22:19Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;The shared bus arbiter 63F81 &lt;br class='autobr' /&gt;
On a multi-core 63F09 build, all cores share a single external bus interface &#8212; one set of address, data, and control pins. 63F81.vhd instantiates one DMC_63F41 (with its own L1 cache, see the companion document) per core, and arbitrates which core's signals actually drive that shared interface at any given moment. &lt;br class='autobr' /&gt;
One master at a time, chosen by a sticky round robin &lt;br class='autobr' /&gt;
The arbiter tracks a single integer, SIGNAL_LAST_ACTIVE_CPU &#8212; the index of the core&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/peripherals/" rel="directory"&gt;Peripherals&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;h2 class=&#034;spip&#034;&gt;The shared bus arbiter 63F81&lt;/h2&gt;
&lt;p&gt;On a multi-core 63F09 build, all cores share a single external bus interface &#8212; one set of address, data, and control pins. &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;63F81.vhd&lt;/code&gt; instantiates one &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;DMC_63F41&lt;/code&gt; (with its own L1 cache, see the companion document) per core, and arbitrates which core's signals actually drive that shared interface at any given moment.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;One master at a time, chosen by a sticky round robin&lt;/h2&gt;
&lt;p&gt;The arbiter tracks a single integer, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;SIGNAL_LAST_ACTIVE_CPU&lt;/code&gt; &#8212; the index of the core currently granted the bus. It is recomputed by a purely combinational process, sensitive only to the per-core &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_REQUEST&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK_REQUEST&lt;/code&gt; vectors:&lt;/p&gt;
&lt;div class=&#034;precode&#034;&gt;&lt;pre class='spip_code spip_code_block' dir='ltr' style='text-align:left;'&gt;&lt;code&gt;for i in 0 to NCPUS loop CURRENT_CPU := (SIGNAL_LAST_ACTIVE_CPU + i) mod NCPUS; if ((BUS_REQUEST(CURRENT_CPU)='1') or (LOCK_REQUEST(CURRENT_CPU)='1')) and (REG_CONFIGURATION(CURRENT_CPU)='1') then exit; end if; end loop; SIGNAL_LAST_ACTIVE_CPU &lt;= CURRENT_CPU;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The search always starts from the &lt;strong&gt;current&lt;/strong&gt; master (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;i=0&lt;/code&gt; maps back to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;SIGNAL_LAST_ACTIVE_CPU&lt;/code&gt; itself). As long as that core keeps asserting &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_REQUEST&lt;/code&gt; or &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK_REQUEST&lt;/code&gt; and remains enabled in &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;REG_CONFIGURATION&lt;/code&gt;, the loop exits immediately on its very first iteration and &lt;strong&gt;the same core keeps the bus&lt;/strong&gt; &#8212; there is no forced, time-sliced rotation while a master keeps asking. Only once the current master's own request drops (or it is disabled) does the search continue forward, round-robin, to the next requesting, enabled core. If nothing at all is requesting, the loop runs to completion (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;i=NCPUS&lt;/code&gt; wraps back to the current master) and the arbiter simply parks on the same core by default.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Grants are a strict one-hot&lt;/h2&gt;
&lt;p&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED&lt;/code&gt;, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK_GRANTED&lt;/code&gt; and &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;REG_CURRENT_CPU&lt;/code&gt; are all derived from &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;SIGNAL_LAST_ACTIVE_CPU&lt;/code&gt; alone, in a second, equally combinational process: every entry is cleared, then exactly the one at index &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;SIGNAL_LAST_ACTIVE_CPU&lt;/code&gt; is set. Exactly one core ever holds the bus (and the lock) at a time; every other core's &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED(i)&lt;/code&gt; reads &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;'0'&lt;/code&gt; and its request simply waits for its turn.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Only the master sees the real external signals&lt;/h2&gt;
&lt;p&gt;The same process default-initializes every core's &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_MRDY&lt;/code&gt;, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_DMA_BREQ_n&lt;/code&gt;, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_D_IN&lt;/code&gt; and &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_CACHEABLE&lt;/code&gt; to an inert value (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_MRDY(i)&lt;='1'&lt;/code&gt;, meaning &#8220;never wait&#8221;, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_D_IN(i)&lt;=&lt;/code&gt;all-ones, and so on) for &lt;strong&gt;every&lt;/strong&gt; core, then overwrites only the current master's own entry with the real, top-level signal &#8212; &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_MRDY (SIGNAL_LAST_ACTIVE_CPU) &lt;= MRDY&lt;/code&gt;, and likewise for the other three. A core that does not currently hold the bus is therefore never stalled by a memory transaction it is not even part of; it keeps running against its own private L1 cache exactly as if it were the only core in the system. The chip-level &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;MMU_MRDY&lt;/code&gt; output follows the identical idiom, one level up &#8212; &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;MMU_MRDY &lt;= CORE_MMU_MRDY(SIGNAL_LAST_ACTIVE_CPU)&lt;/code&gt; &#8212; deliberately &lt;strong&gt;not&lt;/strong&gt; an &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;OR&lt;/code&gt; across all cores, since that would only stay correct for as long as every non-master core's own &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CORE_MMU_MRDY&lt;/code&gt; output happens to be an unconditional &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;'1'&lt;/code&gt; (a property of &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;63F29.vhd&lt;/code&gt;, not guaranteed by the arbiter itself).&lt;/p&gt;
&lt;p&gt;The chip-level bus signals proper &#8212; &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E_n&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;Q&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;RW_n&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;A&lt;/code&gt;/ &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;D_OUT&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BA&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BS&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;FIC&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;VMA&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;MEMCLK&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CLKVECT&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_MASTER&lt;/code&gt; &#8212; are all simply the current master's own per-core signals, muxed by &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;SIGNAL_LAST_ACTIVE_CPU&lt;/code&gt;: &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E &lt;= CPU_E(SIGNAL_LAST_ACTIVE_CPU)&lt;/code&gt;, and so on for every one of them.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Protecting E across a bus hand-off&lt;/h2&gt;
&lt;p&gt;Each core keeps generating its own local &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E_LOCAL&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E_n_LOCAL&lt;/code&gt; continuously, bus or no bus &#8212; a core not holding the bus still runs against its own cache. But the &lt;strong&gt;instant&lt;/strong&gt; a core is granted the bus, its own local &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E&lt;/code&gt; phase may not line up cleanly with the moment ownership actually changed hands. A small per-core shift register guards against this:&lt;/p&gt;
&lt;div class=&#034;precode&#034;&gt;&lt;pre class='spip_code spip_code_block' dir='ltr' style='text-align:left;'&gt;&lt;code&gt;if BUS_GRANTED(i) = '1' then if REGISTER_BUS_GRANTED(1) = '0' then CPU_E(i) &lt;= '1'; CPU_E_n(i) &lt;= '0'; -- held, right after the grant else CPU_E(i) &lt;= E_LOCAL; CPU_E_n(i) &lt;= E_n_LOCAL; -- settled, pass through end if; else CPU_E(i) &lt;= E_LOCAL; CPU_E_n(i) &lt;= E_n_LOCAL; -- not the master: always local end if;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;REGISTER_BUS_GRANTED&lt;/code&gt; is a 2-bit shift register, sampling &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED(i)&lt;/code&gt; on the falling edge of each of the four &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CLKVECT&lt;/code&gt; phases in turn. Right after a grant, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_E(i)&lt;/code&gt; is held high for as long as &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED(i)&lt;/code&gt; has not yet been seen stably asserted across two such samples; once it has, the core's real &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E_LOCAL&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E_n_LOCAL&lt;/code&gt; is allowed through as the externally-visible &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_E(i)&lt;/code&gt;. The register is reset the instant &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED(i)&lt;/code&gt; falls back to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;'0'&lt;/code&gt;, so the very next hand-off to this core goes through the same settling window again.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;The lock mechanism&lt;/h2&gt;
&lt;p&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK_REQUEST&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK_GRANTED&lt;/code&gt; give a core a way to hold the bus for an indivisible sequence (for instance an atomic read-modify-write, or the dedicated &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;UNLOCK&lt;/code&gt; instructions). The arbiter treats a lock request exactly like a bus request for the purpose of keeping a core selected &#8212; either one is enough to make the round-robin search stop on that core &#8212; and grants it in the very same one-hot process as &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED&lt;/code&gt;, at the same index. As long as a core keeps &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCK_REQUEST&lt;/code&gt; asserted, the sticky round robin above guarantees no other core can become &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;SIGNAL_LAST_ACTIVE_CPU&lt;/code&gt; in between.&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>DMC 63F41</title>
		<link>https://63f09.systella.fr/soc-63f09/peripherals/article/dmc-63f41</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/peripherals/article/dmc-63f41</guid>
		<dc:date>2024-08-23T17:22:01Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;The 63F09 L1 data cache (&lt;span class=&#034;caps&#034;&gt;DMC&lt;/span&gt; 63F41) &lt;br class='autobr' /&gt;
Each 63F09 core embeds its own private L1 data cache. It is a direct-mapped, write-through cache: every store is propagated to external memory immediately, and no dirty write-back ever happens. &lt;br class='autobr' /&gt;
A write-back policy would require flushing on every context switch and would delay writes aimed at memory-mapped peripherals &#8212; both unacceptable for this design. Write-through sidesteps both problems at the cost of writing external memory on every store, hit or&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/peripherals/" rel="directory"&gt;Peripherals&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;h2 class=&#034;spip&#034;&gt;The 63F09 L1 data cache (&lt;span class=&#034;caps&#034;&gt;DMC&lt;/span&gt; 63F41)&lt;/h2&gt;
&lt;p&gt;Each 63F09 core embeds its own private L1 data cache. It is a &lt;strong&gt;direct-mapped, write-through&lt;/strong&gt; cache: every store is propagated to external memory immediately, and &lt;strong&gt;no dirty write-back ever happens&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A write-back policy would require flushing on every context switch and would delay writes aimed at memory-mapped peripherals &#8212; both unacceptable for this design. Write-through sidesteps both problems at the cost of writing external memory on every store, hit or miss.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Address layout and storage&lt;/h2&gt;
&lt;p&gt;A physical address is 36 bits, split as:&lt;/p&gt;
&lt;ul class=&#034;spip&#034; role=&#034;list&#034;&gt;&lt;li&gt;&lt;strong&gt;&lt;span class=&#034;caps&#034;&gt;TAG&lt;/span&gt;&lt;/strong&gt; &#8212; 20 bits, upper address bits&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class=&#034;caps&#034;&gt;BLOCK&lt;/span&gt;&lt;/strong&gt; &#8212; 16 bits, lower address bits, used directly as the row index into the cache&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Because &lt;span class=&#034;caps&#034;&gt;BLOCK&lt;/span&gt; covers the entire low 16 bits of the address with no further line/offset structure, the cache holds &lt;strong&gt;one row per byte&lt;/strong&gt; over a 64 &lt;span class=&#034;caps&#034;&gt;KB&lt;/span&gt; window &#8212; there is no cache-line granularity beyond a single byte. Two block RAMs are addressed in parallel by the same &lt;span class=&#034;caps&#034;&gt;BLOCK&lt;/span&gt; index:&lt;/p&gt;
&lt;ul class=&#034;spip&#034; role=&#034;list&#034;&gt;&lt;li&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;VALID_64k&lt;/code&gt; (component &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;RAM_61F64x1&lt;/code&gt;) &#8212; one bit of &lt;strong&gt;&lt;span class=&#034;caps&#034;&gt;VALID&lt;/span&gt;&lt;/strong&gt;, the 20-bit &lt;strong&gt;&lt;span class=&#034;caps&#034;&gt;TAG&lt;/span&gt;&lt;/strong&gt;, and one &lt;strong&gt;&lt;span class=&#034;caps&#034;&gt;DIRTY&lt;/span&gt;&lt;/strong&gt; bit per other core in the system, for every block index&lt;/li&gt;&lt;li&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CACHE_64K&lt;/code&gt; (component &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;RAM_61F512&lt;/code&gt;) &#8212; the cached data byte itself, for every block index&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Both are true block RAMs, clocked by the same signal, so a tag lookup and a data lookup for the same block always complete together.&lt;/p&gt;
&lt;p&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CURRENT_TAG&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CURRENT_BLOCK&lt;/code&gt; are pure combinational functions of the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt;'s own address bus &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_A&lt;/code&gt; &#8212; they track the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt;'s requested address instantly, with no latency of their own.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;State machine and the fast-path budget&lt;/h2&gt;
&lt;p&gt;The controller is a state machine with a strict latency budget for the common case: &lt;strong&gt;a cache hit costs exactly one &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; cycle&lt;/strong&gt;, no more (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE&lt;/code&gt; or &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE_2&lt;/code&gt; &#8594; &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;COMPARE_TAG&lt;/code&gt; &#8594; &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;READ_CACHE&lt;/code&gt; &#8594;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;READ_CACHE_2&lt;/code&gt;), four ticks, atching one full rotation of the four phase-shifted clocks that also drive the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt;'s own &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E&lt;/code&gt; clock. &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE_2&lt;/code&gt; are two functionally identical states that simply alternate to balance clock-tree fan-out while the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; address is unchanged or &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_VMA&lt;/code&gt; is deasserted; as soon as a new address is presented, the machine moves to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;COMPARE_TAG&lt;/code&gt;.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Read hit&lt;/h2&gt;
&lt;p&gt;In &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;COMPARE_TAG&lt;/code&gt;, for a &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; read, the controller compares the requested tag against the stored one.&lt;/p&gt;
&lt;p&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;DIRTY_FLAG&lt;/code&gt; folds in the cross-core coherency state: even a matching, valid tag is treated as a miss if another core has more recently written that same block. On a genuine hit, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_REQUEST&lt;/code&gt; is deasserted, the external address bus is disabled, and the machine proceeds straight to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;READ_CACHE&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;READ_CACHE_2&lt;/code&gt;, which simply present &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CACHE_D_OUT&lt;/code&gt; (the data &lt;span class=&#034;caps&#034;&gt;BRAM&lt;/span&gt;'s output) to the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; as &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CPU_D_IN&lt;/code&gt; and resynchronize the machine on the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt;'s own &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;E&lt;/code&gt; clock before returning to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE&lt;/code&gt;. &lt;strong&gt;A cache hit therefore costs exactly one &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; cycle&lt;/strong&gt;, matching what a direct, uncached read would already cost &#8212; the cache adds no overhead of its own on the hit path.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Read miss&lt;/h2&gt;
&lt;p&gt;If the tag does not match, is not valid, or is marked dirty by another core, the controller requests the external bus and, once granted, moves to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;ALLOCATE&lt;/code&gt;. &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;ALLOCATE&lt;/code&gt; drives the real address out and waits for the external memory's own ready signal (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;MRDY&lt;/code&gt;, self-looping on &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;ALLOCATE&lt;/code&gt; while it is low); once ready, &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;ALLOCATE_2&lt;/code&gt; both hands the fetched data to the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; &lt;strong&gt;and&lt;/strong&gt; writes it into the cache in the same cycle before returning to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE&lt;/code&gt;. A block that is not cacheable (peripheral space, for instance) is simply never marked valid, so it is always re-fetched. &lt;strong&gt;Populating a new cache entry this way costs 1.5 &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; cycles&lt;/strong&gt; in the fast case &#8212; bus already free, external memory ready without extra wait &#8212; on top of the read itself; a busy bus or a slower external memory extends this by however long &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;BUS_GRANTED&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;MRDY&lt;/code&gt; actually take to arrive.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Write (always write-through)&lt;/h2&gt;
&lt;p&gt;&lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; writes never distinguish hit from miss: a store always goes both to the cache row &lt;strong&gt;and&lt;/strong&gt; out to external memory, in the same transaction. From &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;COMPARE_TAG&lt;/code&gt;, the controller requests the bus and, once granted, enters &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;WRITE_THROUGH&lt;/code&gt;, which drives the address and data out and updates the cache, in the very same cycle it exits toward &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;WRITE_THROUGH_2&lt;/code&gt;. &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;WRITE_THROUGH_2&lt;/code&gt; (and, on multi-core configurations, an extra &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;WRITE_THROUGH_3&lt;/code&gt; resync tick &#8212; see below) waits for the external write to actually complete before returning to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;IDLE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because the write is unconditional (never gated on a hit), external memory is guaranteed to always hold the up-to-date value for everyaddress ever written &#8212; the precondition that lets the cache skip any write-back logic entirely.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt;Cross-core invalidation&lt;/h2&gt;
&lt;p&gt;On a multi-core build, each core's cache carries one &lt;strong&gt;&lt;span class=&#034;caps&#034;&gt;DIRTY&lt;/span&gt;&lt;/strong&gt; bit per &lt;strong&gt;other&lt;/strong&gt; core for every block, plus a matching &lt;strong&gt;Cross Cache Signaling&lt;/strong&gt; (&lt;span class=&#034;caps&#034;&gt;CCS&lt;/span&gt;) bus that broadcasts every write to all other cores:&lt;/p&gt;
&lt;ul class=&#034;spip&#034; role=&#034;list&#034;&gt;&lt;li&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_WRITE_PULSE&lt;/code&gt; &#8212; a single-tick pulse, raised exactly on the&lt;br class='autobr' /&gt;
&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;WRITE_THROUGH&lt;/code&gt;&#8594;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;WRITE_THROUGH_2&lt;/code&gt; transition (never earlier), because that is the one point where the bus is already known to be granted and the write is certain to actually happen &#8212; broadcasting any earlier would risk announcing a write that never occurs.&lt;/li&gt;&lt;li&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_ADDRESS_OUT&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_ADDRESS_RW_n_OUT&lt;/code&gt; &#8212; the written address and direction, broadcast alongside the pulse, received by every other core as &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_ADDRESS_IN(i)&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_ADDRESS_RW_n_IN(i)&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Each core runs a separate &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;EXTERNAL_DIRTY_SUPERVISION&lt;/code&gt; process per remote core, watching this broadcast. It reads its own tag/valid &lt;span class=&#034;caps&#034;&gt;BRAM&lt;/span&gt;&lt;br class='autobr' /&gt;
through a second port at the broadcast block index; if the tag matches and the entry is valid, it sets its own &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;DIRTY_OUT(i)&lt;/code&gt; bit for that block. Back in &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;COMPARE_TAG&lt;/code&gt;, any core's own read hit test folds in every other core's dirty bit for the block &#8212; a block flagged dirty by a peer is treated as a miss and re-fetched from external memory, guaranteeing the freshest value is picked up rather than a stale local copy.&lt;/p&gt;
&lt;p&gt;This snoop path has its own read-latency compensation (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;COMPARE_TAG_2&lt;/code&gt;, an explicit extra settling tick before trusting &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;TAG_DIRTY_OUT&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_VALID&lt;/code&gt;), deliberately added because this particular path carries no &#8220;one &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt; cycle&#8221; budget constraint &#8212; unlike the &lt;span class=&#034;caps&#034;&gt;CPU&lt;/span&gt;-facing hit/miss path described above, which cannot afford it at all.&lt;/p&gt;
&lt;p&gt;&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCAL_CACHE_MRDY&lt;/code&gt; further gates the whole state-commit process on multi-core builds: a core only advances its own state machine while every peer reports &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CCS_MRDY_IN(i)='1'&lt;/code&gt;, so no core commits mid-way through a cross-core invalidation window. On single-core builds (&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;NCPUS=1&lt;/code&gt;), all of this collapses away &#8212; &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;CACHE_MRDY&lt;/code&gt;/&lt;code class='spip_code spip_code_inline' dir='ltr'&gt;LOCAL_CACHE_MRDY&lt;/code&gt; are simply tied to &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;'1'&lt;/code&gt;, and &lt;code class='spip_code spip_code_inline' dir='ltr'&gt;DIRTY_FLAG&lt;/code&gt; is always false.&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>PTM</title>
		<link>https://63f09.systella.fr/soc-63f09/programming-examples/article/ptm</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/programming-examples/article/ptm</guid>
		<dc:date>2024-06-17T08:32:47Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;``` &lt;span class=&#034;caps&#034;&gt;ORG&lt;/span&gt; $&lt;span class=&#034;caps&#034;&gt;FFFFFF00&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDMD&lt;/span&gt; #$31 &lt;span class=&#034;caps&#034;&gt;LDS&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFE0000&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDU&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFDF000&lt;/span&gt; * Direct mode: address is built with &lt;span class=&#034;caps&#034;&gt;DS&lt;/span&gt;:&lt;span class=&#034;caps&#034;&gt;DP&lt;/span&gt;:8 bits offset &lt;span class=&#034;caps&#034;&gt;LDDS&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFE&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDDP&lt;/span&gt; #$F0 * Configure &lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt; (&lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt;(0) &lt;= 1). * &lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt;(0) is connected to &lt;span class=&#034;caps&#034;&gt;PTM1&lt;/span&gt;.G(3) &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #%00000000 &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt;+1 &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #%00000001 &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #%00000100 &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt;+1 &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #%00000001 &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;PIA0&lt;/span&gt; * 1 : source (0 : external) * 2 : mode (0 : 16 bits)&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/programming-examples/" rel="directory"&gt;Programming examples&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;div class=&#034;precode&#034;&gt;&lt;pre class='spip_code spip_code_block' dir='ltr' style='text-align:left;'&gt;&lt;code&gt; ORG $FFFFFF00 LDMD #$31 LDS #$FFFE0000 LDU #$FFFDF000 * Direct mode: address is built with DS:DP:8 bits offset LDDS #$FFFE LDDP #$F0 * Configure PIA0 (PIA0(0) &lt;= 1). * PIA0(0) is connected to PTM1.G(3) LDA #%00000000 STA &lt;PIA0+1 LDA #%00000001 STA &lt;PIA0 LDA #%00000100 STA &lt;PIA0+1 LDA #%00000001 STA &lt;PIA0 * 1 : source (0 : external) * 2 : mode (0 : 16 bits) * 6 : interrupt enabled * Write to CR2 LDDP #$D0 LDA #%00000001 STA &lt;PTM1+1 * Write to CR1 (CR2(0) = 1) LDA #%00000000 STA &lt;PTM1 * Write to CR2 LDA #%00000000 STA &lt;PTM1+1 * Write to CR3 (CR2(0) = 0) LDA #%11111010 STA &lt;PTM1 * Write to LATCH3 LDD #$0020 STD &lt;PTM1+6 * PTM1.3 : Timer interval mode * Now, try to start timer BSR EDGE BSR EDGE STA &lt;PIA0 * Now, try to restart timer LDB #10 L1: DECB BNE L1 LDDP #$F0 LDA #%00000000 STA &lt;PIA0 LOOP: BRA LOOP * Abort simulation FCB $CF EDGE: LDDP #$F0 LDA #%00000000 STA &lt;PIA0 LDA #%00000001 STA &lt;PIA0 RTS ORG $FFFFFF80 PSHS D,W,DP LDDP #$D0 * Read status register LDB &lt;PTM0+1 * Read timers LDW &lt;PTM0+2 LDW &lt;PTM0+4 PULS D,W,DP RTI ORG $FFFFFFA0 PSHS D,W,DP LDDP #$D0 * Read status register LDB &lt;PTM1+1 * Read timers LDW &lt;PTM1+6 PULS D,W,DP RTI TWI0 EQU $FFFEB000 SPI0 EQU $FFFEC000 PTM0 EQU $FFFED000 PTM1 EQU $FFFED008 ACIA0 EQU $FFFEE000 ACIA1 EQU $FFFEE004 PIA0 EQU $FFFEF000 PIA1 EQU $FFFEF002 PIA2 EQU $FFFEF004 PIA3 EQU $FFFEF006 PIA4 EQU $FFFEF008 * PTM1 interrupt ORG $FFFFFFE8 FDB $FFA0 * PTM0 interrupt ORG $FFFFFFEA FDB $FF80 ORG $FFFFFFF0 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $FF00 END &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>SPI</title>
		<link>https://63f09.systella.fr/soc-63f09/programming-examples/article/spi</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/programming-examples/article/spi</guid>
		<dc:date>2024-06-17T08:27:32Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;``` &lt;span class=&#034;caps&#034;&gt;ORG&lt;/span&gt; $&lt;span class=&#034;caps&#034;&gt;FFFFFF00&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDMD&lt;/span&gt; #$31 &lt;span class=&#034;caps&#034;&gt;LDS&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFF0000&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDU&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFEF000&lt;/span&gt; * Direct mode: address is built with &lt;span class=&#034;caps&#034;&gt;DS&lt;/span&gt;:&lt;span class=&#034;caps&#034;&gt;DP&lt;/span&gt;:8 bits offset &lt;span class=&#034;caps&#034;&gt;LDDS&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFF&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDDP&lt;/span&gt; #$00 * &lt;span class=&#034;caps&#034;&gt;SPI0&lt;/span&gt; * Internal registers: * &lt;span class=&#034;caps&#034;&gt;SPI0&lt;/span&gt;+0: data register * &lt;span class=&#034;caps&#034;&gt;SPI0&lt;/span&gt;+1: control register &lt;br class='autobr' /&gt;
* &lt;span class=&#034;caps&#034;&gt;SPI0&lt;/span&gt; control register * Configure divisor (1'000'000) &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #%00000001 &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt; TX_EMPTY = 1 * &lt;span class=&#034;caps&#034;&gt;TST&lt;/span&gt; Z=0 =&gt; TX_EMPTY = 1 * &lt;span class=&#034;caps&#034;&gt;TST&lt;/span&gt; Z=1 =&gt; TX_EMPTY = 0 &lt;span class=&#034;caps&#034;&gt;BEQ&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;WAIT&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;RTS&lt;/span&gt; &lt;br class='autobr' /&gt;
&lt;span class=&#034;caps&#034;&gt;WAIT2&lt;/span&gt;: &lt;span class=&#034;caps&#034;&gt;LDW&lt;/span&gt; #500 &lt;span class=&#034;caps&#034;&gt;BOUCLE&lt;/span&gt;: &lt;span class=&#034;caps&#034;&gt;DECW&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;BNE&lt;/span&gt;&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/programming-examples/" rel="directory"&gt;Programming examples&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;div class=&#034;precode&#034;&gt;&lt;pre class='spip_code spip_code_block' dir='ltr' style='text-align:left;'&gt;&lt;code&gt; ORG $FFFFFF00 LDMD #$31 LDS #$FFFF0000 LDU #$FFFEF000 * Direct mode: address is built with DS:DP:8 bits offset LDDS #$FFFF LDDP #$00 * SPI0 * Internal registers: * SPI0+0: data register * SPI0+1: control register * SPI0 control register * Configure divisor (1'000'000) LDA #%00000001 STA &lt;SPI0+1 LDD #5 STD &lt;SPI0 LDA #%00000001 STA &lt;SPI0+1 LDW &lt;SPI0 * Configure SPI0 LDA #%00100000 STA &lt;SPI0+1 * Send data JSR WAIT LDA #$AA STA &lt;SPI0 JSR WAIT LDA #$A5 STA &lt;SPI0 JSR WAIT2 * Abort simulation FCB $CF WAIT: LDB &lt;SPI0+1 ANDB #$40 TSTB * loop while SPI0_CC(TX_EMPTY) = 0 * SPI0_CC and #$40 = #$40 =&gt; TX_EMPTY = 1 * TST Z=0 =&gt; TX_EMPTY = 1 * TST Z=1 =&gt; TX_EMPTY = 0 BEQ WAIT RTS WAIT2: LDW #500 BOUCLE: DECW BNE BOUCLE RTS * IRQ SPI0 ORG $FFFFFF80 * Read SPI RX register to release interrupt request PSHU B LDB &lt;SPI0 PULU B RTI TWI0 EQU $FFFEB000 SPI0 EQU $FFFEC000 PTM0 EQU $FFFED000 PTM1 EQU $FFFED008 ACIA0 EQU $FFFEE000 ACIA1 EQU $FFFEE004 PIA0 EQU $FFFEF000 PIA1 EQU $FFFEF002 PIA2 EQU $FFFEF004 PIA3 EQU $FFFEF006 PIA4 EQU $FFFEF008 * TWI0 interrupt ORG $FFFFFFDA FDB $FF80 ORG $FFFFFFF0 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 END &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>TWI</title>
		<link>https://63f09.systella.fr/soc-63f09/programming-examples/article/twi</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/programming-examples/article/twi</guid>
		<dc:date>2024-06-14T06:40:13Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;Example ``` &lt;span class=&#034;caps&#034;&gt;ORG&lt;/span&gt; $&lt;span class=&#034;caps&#034;&gt;FFFF0000&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDMD&lt;/span&gt; #$31 &lt;span class=&#034;caps&#034;&gt;LDS&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFE0000&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDU&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFDF000&lt;/span&gt; * Direct mode: address is built with &lt;span class=&#034;caps&#034;&gt;DS&lt;/span&gt;:&lt;span class=&#034;caps&#034;&gt;DP&lt;/span&gt;:8 bits offset * i2c controller is at $&lt;span class=&#034;caps&#034;&gt;FFFEB000&lt;/span&gt;-$&lt;span class=&#034;caps&#034;&gt;FFFEB003&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDDS&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFE&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;LDDP&lt;/span&gt; #$B0 * &lt;span class=&#034;caps&#034;&gt;TWI0&lt;/span&gt; control register &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #%00000000 ; polling mode &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;TWI0&lt;/span&gt;+2 * Set &lt;span class=&#034;caps&#034;&gt;TWI0&lt;/span&gt; clock divisor &lt;span class=&#034;caps&#034;&gt;LDD&lt;/span&gt; #0 &lt;span class=&#034;caps&#034;&gt;STD&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;TWI0&lt;/span&gt;+4 * Set slave address &lt;span class=&#034;caps&#034;&gt;LDD&lt;/span&gt; #$50 &lt;span class=&#034;caps&#034;&gt;STD&lt;/span&gt; &lt;&lt;span class=&#034;caps&#034;&gt;TWI0&lt;/span&gt;+6 &lt;br class='autobr' /&gt;
* Write into $20 &lt;span class=&#034;caps&#034;&gt;LDA&lt;/span&gt; #$20 &lt;span class=&#034;caps&#034;&gt;STA&lt;/span&gt;&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/programming-examples/" rel="directory"&gt;Programming examples&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;div class='spip_document_7 spip_document spip_documents spip_document_image spip_documents_center spip_document_center spip_document_avec_legende' data-legende-len=&#034;57&#034; data-legende-lenx=&#034;x&#034;
&gt;
&lt;figure class=&#034;spip_doc_inner&#034;&gt; &lt;a href='https://63f09.systella.fr/IMG/jpg/i2c.jpg' class=&#034;spip_doc_lien mediabox&#034; type=&#034;image/jpeg&#034;&gt; &lt;img src='https://63f09.systella.fr/IMG/jpg/i2c.jpg?1718446697' width='500' height='197' alt='' /&gt;&lt;/a&gt;
&lt;figcaption class='spip_doc_legende'&gt; &lt;div class='spip_doc_titre '&gt;&lt;strong&gt;i2c transaction with an 24C02 &lt;span class=&#034;caps&#034;&gt;EEPROM&lt;/span&gt; (single and burst)
&lt;/strong&gt;&lt;/div&gt; &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/div&gt;&lt;h2 class=&#034;spip&#034;&gt;Example&lt;/h2&gt;&lt;div class=&#034;precode&#034;&gt;&lt;pre class='spip_code spip_code_block' dir='ltr' style='text-align:left;'&gt;&lt;code&gt; ORG $FFFF0000 LDMD #$31 LDS #$FFFE0000 LDU #$FFFDF000 * Direct mode: address is built with DS:DP:8 bits offset * i2c controller is at $FFFEB000-$FFFEB003 LDDS #$FFFE LDDP #$B0 * TWI0 control register LDA #%00000000 ; polling mode STA &lt;TWI0+2 * Set TWI0 clock divisor LDD #0 STD &lt;TWI0+4 * Set slave address LDD #$50 STD &lt;TWI0+6 * Write into $20 LDA #$20 STA &lt;TWI0 LDA #%00000001 STA &lt;TWI0+1 LBSR TX_EMPTY ; wait until TX register is loaded in buffer LDA #$4E ; data written at address $20 STA &lt;TWI0 LDA #%00001001 STA &lt;TWI0+1 LDB #%00000011 ; wait until STOP state LBSR POLL * Write into $10 and $11 LDA #$10 STA &lt;TWI0 LDA #%00000001 STA &lt;TWI0+1 LDB #%00010001 ; wait until SLAVE ACK after address LBSR POLL LDA #$3F ; data written at address $10 STA &lt;TWI0 LDA #%00000001 STA &lt;TWI0+1 LDB #%00000101 ; wait until WRITE is started LBSR POLL LDA #$24 ; data written at address $11 STA &lt;TWI0 LDA #%00001001 STA &lt;TWI0+1 LDB #%00000011 ; wait until STOP state LBSR POLL * Read addresses $10 (3F) and $11 (24) LDA #$10 STA &lt;TWI0 * Send data (write mode) LDA #%001 STA &lt;TWI0+1 LDB #%00000101 ; wait until WRITE is started BSR POLL * Receive data (read mode with MACK) LDA #%111 STA &lt;TWI0+1 LDB #%00001000 ; wait until MASTER_ACK state BSR POLL * Wait LDW #$0200 WAIT: DECW BNE WAIT LDF &lt;TWI0 ; read data (#$3F) * TWI0 control register ; IRQ mode LDA #%00100000 STA &lt;TWI0+2 * Receive data (read mode without MACK) LDA #%011 STA &lt;TWI0+1 LDB #%00001001 ; wait until NO_MASTER_ACK state BSR POLL * Read addresses $20 (4E) LDA #$20 STA &lt;TWI0 * Send data (write mode) LDA #%001 STA &lt;TWI0+1 BSR WAIT_ACK * Receive data (read mode without MACK) LDA #%011 STA &lt;TWI0+1 LDB #%00000011 ; wait until STOP state BSR POLL * Read addresses $11 (24) LDA #$11 STA &lt;TWI0 * Send data (write mode) LDA #%001 STA &lt;TWI0+1 BSR WAIT_ACK * Receive data (read mode without MACK) LDA #%011 STA &lt;TWI0+1 LDB #%00000011 ; wait until STOP state BSR POLL ABORT: FCB $CF TX_EMPTY: LDA &lt;TWI0+2 ANDA #$40 BEQ TX_EMPTY RTS WAIT_ACK: LDA &lt;TWI0+2 ANDA #$08 BEQ WAIT_ACK RTS POLL: * Wait for READY state LDA &lt;TWI0+3 CMPR A,B BNE POLL CLR &lt;TWI0 RTS * Interruptions ORG $FFFFFF00 LDE &lt;TWI0 RTI TWI0 EQU $FFFEB000 SPI0 EQU $FFFEC000 PTM0 EQU $FFFED000 PTM1 EQU $FFFED008 ACIA0 EQU $FFFEE000 ACIA1 EQU $FFFEE004 PIA0 EQU $FFFEF000 PIA1 EQU $FFFEF002 PIA2 EQU $FFFEF004 PIA3 EQU $FFFEF006 PIA4 EQU $FFFEF008 * TWI0 interrupt ORG $FFFFFFD8 FDB $FF00 ORG $FFFFFFF0 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 FDB $0000 END &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>ROM initialization</title>
		<link>https://63f09.systella.fr/soc-63f09/tools/article/rom-initialization</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/tools/article/rom-initialization</guid>
		<dc:date>2024-06-14T06:38:34Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;System on chip contains 64 Kbytes of read only memory between addresses $&lt;span class=&#034;caps&#034;&gt;FFFF0000&lt;/span&gt; and $&lt;span class=&#034;caps&#034;&gt;FFFFFFFF&lt;/span&gt;. This memory is created with &lt;span class=&#034;caps&#034;&gt;RAM&lt;/span&gt; blocks and initialized in a file created by memblcks.rpl tool. &lt;br class='autobr' /&gt;
memblcks.rpl is a program written in &lt;span class=&#034;caps&#034;&gt;RPL&lt;/span&gt;/2 and takes a &lt;span class=&#034;caps&#034;&gt;SREC&lt;/span&gt; file generated by A09 assembler in 32 bits mode. It splits S-records into bits arrays to create a usable 27F512.vhd file. &lt;br class='autobr' /&gt;
This tool is downloadable from ftp site. &lt;br class='autobr' /&gt;
``` hilbert:[&#160;/vhdl/63F09asmb/tests] &gt; ./memblcks.rpl -A \&#8220;i2c.s09\&#8221;&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/tools/" rel="directory"&gt;Tools&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;System on chip contains 64 Kbytes of read only memory between addresses $&lt;span class=&#034;caps&#034;&gt;FFFF0000&lt;/span&gt; and $&lt;span class=&#034;caps&#034;&gt;FFFFFFFF&lt;/span&gt;. This memory is created with &lt;span class=&#034;caps&#034;&gt;RAM&lt;/span&gt; blocks and initialized in a file created by memblcks.rpl tool.&lt;/p&gt;
&lt;p&gt;memblcks.rpl is a program written in &lt;a href=&#034;http://www.rpl2.net&#034; class=&#034;spip_out&#034; rel=&#034;external&#034;&gt;&lt;span class=&#034;caps&#034;&gt;RPL&lt;/span&gt;/2&lt;/a&gt; and takes a &lt;span class=&#034;caps&#034;&gt;SREC&lt;/span&gt; file generated by A09 assembler in 32 bits mode. It splits S-records into bits arrays to create a usable 27F512.vhd file.&lt;/p&gt;
&lt;p&gt;This tool is downloadable from &lt;a href='https://63f09.systella.fr/files/article/anonymous-ftp' class=&#034;spip_in&#034;&gt;ftp site&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#034;precode&#034;&gt;&lt;pre class='spip_code spip_code_block' dir='ltr' style='text-align:left;'&gt;&lt;code&gt;hilbert:[~/vhdl/63F09asmb/tests] &gt; ./memblcks.rpl -A \&#034;i2c.s09\&#034; +++RPL/2 (R) version 4.1.36 (Jeudi 08/02/2024, 17:52:53 CET) +++Copyright (C) 1989 &#224; 2023, 2024 BERTRAND Jo&#235;l S315FFFF0000113D3110CEFFFE0000CEFFFDF00010C800 S315FFFF0010FFFE10C6B086009702CC0000DD04CC00C1 S315FFFF002050DD068620970086019701170000008C9A S315FFFF0030864E970086099701C603170000008B8639 S315FFFF004010970086019701C611170000007C863FB7 S315FFFF0050970086019701C605170000006D86249756 S315FFFF00600086099701C603170000005E86109700FA S315FFFF007086019701C6058D5286079701C6088D4AE9 S315FFFF008010860200105A26FC11D60086209702869C S315FFFF0090039701C6098D3386209700860197018D49 S315FFFF00A02286039701C6038D218611970086019746 S315FFFF00B0018D1086039701C6038D0FCF96028440ED S315FFFF00C027FA399602840827FA39960310378926C5 S309FFFF00D0F90F0039E7 S309FFFFFF001196003B17 S307FFFFFFD8FF0024 S315FFFFFFF000000000000000000000000000000000FD S9030000FC hilbert:[~/vhdl/63F09asmb/tests] &gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>RAM 61F512</title>
		<link>https://63f09.systella.fr/soc-63f09/peripherals/article/ram-61f512</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/peripherals/article/ram-61f512</guid>
		<dc:date>2024-06-14T06:37:13Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>

-
&lt;a href="https://63f09.systella.fr/soc-63f09/peripherals/" rel="directory"&gt;Peripherals&lt;/a&gt;


		</description>


 <content:encoded>
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>ROM 27F512</title>
		<link>https://63f09.systella.fr/soc-63f09/peripherals/article/rom-27f512</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/peripherals/article/rom-27f512</guid>
		<dc:date>2024-06-14T06:36:44Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;System on chip contains a 64 Kbytes &lt;span class=&#034;caps&#034;&gt;ROM&lt;/span&gt; between $&lt;span class=&#034;caps&#034;&gt;FFFF0000&lt;/span&gt; and $&lt;span class=&#034;caps&#034;&gt;FFFFFFFF&lt;/span&gt;. Memory is created with &lt;span class=&#034;caps&#034;&gt;RAM&lt;/span&gt; blocks in a read only configuration. &lt;br class='autobr' /&gt;
This &lt;span class=&#034;caps&#034;&gt;ROM&lt;/span&gt; is hardcoded and initialized with memblcks.rpl.&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/peripherals/" rel="directory"&gt;Peripherals&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;System on chip contains a 64 Kbytes &lt;span class=&#034;caps&#034;&gt;ROM&lt;/span&gt; between $&lt;span class=&#034;caps&#034;&gt;FFFF0000&lt;/span&gt; and $&lt;span class=&#034;caps&#034;&gt;FFFFFFFF&lt;/span&gt;. Memory is created with &lt;span class=&#034;caps&#034;&gt;RAM&lt;/span&gt; blocks in a read only configuration.&lt;/p&gt;
&lt;p&gt;This &lt;span class=&#034;caps&#034;&gt;ROM&lt;/span&gt; is hardcoded and initialized with &lt;a href='https://63f09.systella.fr/soc-63f09/tools/article/rom-initialization' class=&#034;spip_in&#034;&gt;memblcks.rpl&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>MMU 63F29</title>
		<link>https://63f09.systella.fr/soc-63f09/peripherals/article/mmu-63f29</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/peripherals/article/mmu-63f29</guid>
		<dc:date>2024-06-14T06:35:58Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;* Adresse du vecteur &lt;span class=&#034;caps&#034;&gt;RESET&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;ORG&lt;/span&gt; $&lt;span class=&#034;caps&#034;&gt;FFFF0010&lt;/span&gt; &lt;br class='autobr' /&gt; &lt;span class=&#034;caps&#034;&gt;LDMD&lt;/span&gt; #$31 &lt;br class='autobr' /&gt;
* Ring 0 : on mappe la page des vecteurs d'interruption, &lt;span class=&#034;caps&#034;&gt;MMU&lt;/span&gt; inactive &lt;span class=&#034;caps&#034;&gt;LDQ&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;FFFFFF00&lt;/span&gt; ; adresse logique que l'on doit atteindre. ; seuls les bits 31 &#224; 12 sont pertinents, soit ; $&lt;span class=&#034;caps&#034;&gt;FFFF&lt;/span&gt;:F000. &lt;span class=&#034;caps&#034;&gt;STQ&lt;/span&gt; &gt;TAG_STAGING &lt;br class='autobr' /&gt; &lt;span class=&#034;caps&#034;&gt;LDQ&lt;/span&gt; #$&lt;span class=&#034;caps&#034;&gt;09FFFFFF&lt;/span&gt; ; adresse physique de la page. ; $09 : read, always mapped&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/peripherals/" rel="directory"&gt;Peripherals&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;textarea readonly='readonly' cols='40' rows='126' class='spip_cadre spip_cadre_block' dir='ltr'&gt;* Adresse du vecteur RESET ORG $FFFF0010 LDMD #$31 * Ring 0 : on mappe la page des vecteurs d'interruption, MMU inactive LDQ #$FFFFFF00 ; adresse logique que l'on doit atteindre. ; seuls les bits 31 &#224; 12 sont pertinents, soit ; $FFFF:F000. STQ &gt;TAG_STAGING LDQ #$09FFFFFF ; adresse physique de la page. ; $09 : read, always mapped ; $FFFFFF : adresse de la page physique permettant ; &#224; la MMU de g&#233;n&#233;rer $F:FFFF:Fxxx. STQ &gt;IND_RING0 * Ring 0 : on mappe la page de code actuel (adresse physique $(F)FFFF0010) LDQ #$FFFF0000 STQ &gt;TAG_STAGING LDQ #$0DFFFFF0 ; $FFFF:0000 =&gt; $F:FFFF:0000 STQ &gt;IND_RING0 * Ring 0 : on mappe les deux pages pour le saut dans le ring 1 : * - $00000000-$00000FFF : pile * - $00001000-$00001FFF : programme LDQ #$00000000 STQ &gt;TAG_STAGING ; read + write + always mapped 0000 1011 LDQ #$0BFFFFF2 ; $0000:0000 =&gt; $F:FFFF:2000 STQ &gt;IND_RING1 LDQ #$00001000 STQ &gt;TAG_STAGING ; read + execute + always mapped 0000 1101 LDQ #$0DFFFFF3 ; $0000:1000 =&gt; $F:FFFF:3000 STQ &gt;IND_RING1 * Ring 0 : on mappe la routine SWI &#224; l'adresse $FFFF:8000 LDQ #$FFFF8000 STQ &gt;TAG_STAGING ; read + execute + always mapped 0000 1101 LDQ #$0DFFFFF8 ; $FFFF:8000 =&gt; $F:FFFF:8000 STQ &gt;IND_RING0 * Ring 0 : on mappe la MMU0 LDQ #$FFFD0000 STQ &gt;TAG_STAGING ; read + write + always mapped 0000 1011 LDQ #$0BFFFFD0 ; $FFFD:0000 =&gt; $F:FFFD:0000 STQ &gt;IND_RING0 * Passage dans le ring 1 ; LDA imm&#233;diat 2 cycles, STA &#233;tendu 7 cycles, JMP &#233;tendu 6 cycles LDA #15 ; 7+2+6 STA &gt;FUSE LDA #$81 STA &gt;MMU0 JMP &gt;$00001000 * Le registre FUSE fait que l'on saute dans le ring 1 &#224; cet instant. * Programme &#233;crit &#224; l'adresse $(F)FFFF3000 mais mapp&#233; &#224; l'adresse $00001000. * &#192; partir de l&#224;, on est prot&#233;g&#233; par la MMU. ORG $FFFF3000 RING0: LDS #$0001000 SWI FCB $CF ORG $FFFFF000 PFHANDLER: LDV #$DEADBEEF FCB $CF ; opcode invalide -&gt; arrete le simulateur ORG $FFFF8000 SWITCH_HANDLER: * On est ici dans le ring 0 parce qu'on vient de SWI. On * va tenter de retourner dans le ring 1. LDA #10 ; 2+7+1 STA &gt;FUSE LDA #$81 ; 2 STA &gt;MMU0 ; 7 RTI ; RTI ne prend qu'un seul cycle dans le ring courant. MMU0 EQU $FFFD0000 FUSE EQU MMU0+1 TAG_STAGING EQU MMU0+4 IND_RING0 EQU MMU0+$800 IND_RING1 EQU MMU0+$A00 IND_RING2 EQU MMU0+$C00 IND_RING3 EQU MMU0+$E00 ORG $FFFFFFF0 FDB PFHANDLER ; interruption 0 : TRAP / DIV0 / PAGEFAULT FDB $0000 ; SWI3 FDB $0000 ; SWI2 FDB $0000 ; FIRQ FDB $0000 ; IRQ FDB SWITCH_HANDLER ; SWI FDB $0000 ; NMI FDB $0010 ; RESET END&lt;/textarea&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>SPI 63F52</title>
		<link>https://63f09.systella.fr/soc-63f09/peripherals/article/spi-63f52</link>
		<guid isPermaLink="true">https://63f09.systella.fr/soc-63f09/peripherals/article/spi-63f52</guid>
		<dc:date>2024-06-14T06:35:26Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>63F09</dc:creator>



		<description>
&lt;p&gt;This controller acts as master or slave &lt;span class=&#034;caps&#034;&gt;SPI&lt;/span&gt; device. External signals &lt;span class=&#034;caps&#034;&gt;MISO&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;MOSI&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;SCLK&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt; (16 bits) &lt;br class='autobr' /&gt;
In slave mode, &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt;(0) is mandatory SS_n signal. In master mode, &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt; is used to address slaves's chip select lines. This controller can directly drive 16 &lt;span class=&#034;caps&#034;&gt;SPI&lt;/span&gt; slaves or more slave with an additional address decoder. Internal registers Registers Address Access 7 6 5 4 3 2 1 0 base + 0 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 0 read &lt;span class=&#034;caps&#034;&gt;RX&lt;/span&gt; register write &lt;span class=&#034;caps&#034;&gt;TX&lt;/span&gt; register base + 0 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 1&#160;(&#8230;)&lt;/p&gt;


-
&lt;a href="https://63f09.systella.fr/soc-63f09/peripherals/" rel="directory"&gt;Peripherals&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;This controller acts as master or slave &lt;span class=&#034;caps&#034;&gt;SPI&lt;/span&gt; device.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt; External signals &lt;/h2&gt;&lt;ul class=&#034;spip&#034; role=&#034;list&#034;&gt;&lt;li&gt; &lt;span class=&#034;caps&#034;&gt;MISO&lt;/span&gt;&lt;/li&gt;&lt;li&gt; &lt;span class=&#034;caps&#034;&gt;MOSI&lt;/span&gt;&lt;/li&gt;&lt;li&gt; &lt;span class=&#034;caps&#034;&gt;SCLK&lt;/span&gt;&lt;/li&gt;&lt;li&gt; &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt; (16 bits)&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;In slave mode, &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt;(0) is mandatory SS_n signal. In master mode, &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt; is used to address slaves's chip select lines. This controller can directly drive 16 &lt;span class=&#034;caps&#034;&gt;SPI&lt;/span&gt; slaves or more slave with an additional address decoder.&lt;/p&gt;
&lt;h2 class=&#034;spip&#034;&gt; Internal registers &lt;/h2&gt;&lt;table class=&#034;table spip&#034;&gt;
&lt;caption&gt;Registers&lt;/caption&gt;
&lt;thead&gt;&lt;tr class='row_first'&gt;&lt;th id='idb81d_c0'&gt; Address &lt;/th&gt;&lt;th id='idb81d_c1'&gt; Access &lt;/th&gt;&lt;th id='idb81d_c2'&gt; 7 &lt;/th&gt;&lt;th id='idb81d_c3'&gt; 6 &lt;/th&gt;&lt;th id='idb81d_c4'&gt; 5 &lt;/th&gt;&lt;th id='idb81d_c5'&gt; 4 &lt;/th&gt;&lt;th id='idb81d_c6'&gt; 3 &lt;/th&gt;&lt;th id='idb81d_c7'&gt; 2 &lt;/th&gt;&lt;th id='idb81d_c8'&gt; 1 &lt;/th&gt;&lt;th id='idb81d_c9'&gt; 0 &lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class='row_odd odd'&gt;
&lt;td rowspan='2' headers='idb81d_c0'&gt;base + 0 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 0&lt;/td&gt;
&lt;td headers='idb81d_c1'&gt;read&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;&lt;span class=&#034;caps&#034;&gt;RX&lt;/span&gt; register&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_even even'&gt;
&lt;td headers='idb81d_c1'&gt;write&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;&lt;span class=&#034;caps&#034;&gt;TX&lt;/span&gt; register&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_odd odd'&gt;
&lt;td headers='idb81d_c0'&gt;base + 0 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 1&lt;/td&gt;
&lt;td headers='idb81d_c1'&gt;read/write&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;Clock divisor (&lt;span class=&#034;caps&#034;&gt;MSB&lt;/span&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_even even'&gt;
&lt;td rowspan='2' headers='idb81d_c0'&gt;base + 1&lt;/td&gt;
&lt;td rowspan='2' headers='idb81d_c1'&gt;read/write&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;Control register&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_odd odd'&gt;
&lt;td headers='idb81d_c2'&gt;BUSY_n/&lt;span class=&#034;caps&#034;&gt;RX&lt;/span&gt; data ready&lt;/td&gt;
&lt;td headers='idb81d_c3'&gt;&lt;span class=&#034;caps&#034;&gt;TX&lt;/span&gt; empty&lt;/td&gt;
&lt;td headers='idb81d_c4'&gt;&lt;span class=&#034;caps&#034;&gt;RX&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;IRQ&lt;/span&gt; enabled&lt;/td&gt;
&lt;td headers='idb81d_c5'&gt;&lt;span class=&#034;caps&#034;&gt;TX&lt;/span&gt; &lt;span class=&#034;caps&#034;&gt;IRQ&lt;/span&gt; enabled&lt;/td&gt;
&lt;td headers='idb81d_c6'&gt;&lt;span class=&#034;caps&#034;&gt;CPOL&lt;/span&gt;&lt;/td&gt;
&lt;td headers='idb81d_c7'&gt;&lt;span class=&#034;caps&#034;&gt;CPHA&lt;/span&gt;&lt;/td&gt;
&lt;td headers='idb81d_c8'&gt;Slave &lt;span class=&#034;caps&#034;&gt;SPI&lt;/span&gt;&lt;/td&gt;
&lt;td headers='idb81d_c9'&gt;Clock divisor access&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_even even'&gt;
&lt;td headers='idb81d_c0'&gt;base + 1 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 1&lt;/td&gt;
&lt;td headers='idb81d_c1'&gt;read/write&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;Clock divisor (&lt;span class=&#034;caps&#034;&gt;LSB&lt;/span&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_odd odd'&gt;
&lt;td headers='idb81d_c0'&gt;base + 2 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 0&lt;/td&gt;
&lt;td headers='idb81d_c1'&gt;read/write&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;Chip select register (&lt;span class=&#034;caps&#034;&gt;MSB&lt;/span&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;tr class='row_even even'&gt;
&lt;td headers='idb81d_c0'&gt;base + 3 when &lt;span class=&#034;caps&#034;&gt;CC&lt;/span&gt;(0) = 0&lt;/td&gt;
&lt;td headers='idb81d_c1'&gt;read/write&lt;/td&gt;
&lt;td colspan='8' headers='idb81d_c2'&gt;Chip select register (&lt;span class=&#034;caps&#034;&gt;LSB&lt;/span&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;h2 class=&#034;spip&#034;&gt; Notes &lt;/h2&gt;
&lt;p&gt;Please note that &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt;(0) is only used to read or write clock divisor register. This bit returns to 0 after first access to clock register (&lt;span class=&#034;caps&#034;&gt;LSB&lt;/span&gt;). Chip select register cannot be selected when &lt;span class=&#034;caps&#034;&gt;CS&lt;/span&gt;(0) = 1 (write operation is ignored and read operation always returns $00).&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>



</channel>

</rss>
