{"id":557,"date":"2019-05-05T13:40:25","date_gmt":"2019-05-05T13:40:25","guid":{"rendered":"https:\/\/justanotherelectronicsblog.com\/?p=557"},"modified":"2019-05-05T13:40:27","modified_gmt":"2019-05-05T13:40:27","slug":"turning-a-cpu-into-a-soc","status":"publish","type":"post","link":"https:\/\/justanotherelectronicsblog.com\/?p=557","title":{"rendered":"Turning a CPU into a SoC"},"content":{"rendered":"\n<p>In my previous blog I wrote about a one page CPU in SpinalHDL. But just a CPU is a bit boring, time to turn it into a full System on Chip by adding memory, peripherals and even a UART bootloader. One of the great things of Spinal is the existing libraries, making adding some peripherals a lot less work compared to traditional  hardware design languages.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"764\" height=\"662\" src=\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg\" alt=\"\" class=\"wp-image-562\" srcset=\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg 764w, https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0-300x260.jpg 300w\" sizes=\"auto, (max-width: 764px) 100vw, 764px\" \/><\/figure>\n\n\n\n<!--more-->\n\n\n\n<p>So, first things first, adding some instruction and data memory. Spinal supports generating memory with just a single line of code. So to generate 1Kword of RAM and 1K of instruction memory, the needed code is just this<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val RAM = Mem(Bits(8 bits),wordCount = 1024)\nval ROM = Mem(Bits(16 bits),wordCount = 1024)<\/pre>\n\n\n\n<p>Of course, reading and writing to memory is also required, luckily it&#8217;s fairly easy to do so as well. Loading a file in the ROM can easily be done, as the Hextools library support reading in an Intel hex file. The code to read and write from memory is straightforward as well, and some more info can be found the related <a href=\"https:\/\/spinalhdl.github.io\/SpinalDoc-RTD\/SpinalHDL\/Sequential%20logic\/memory.html\">Spinal website.<\/a><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/default program\nHexTools.initRam(ROM, onChipRamHexFile, 0x0)\n\nRAM.write(\n\tenable  = areaCPU.CPU.io.we_ram,\n\taddress = areaCPU.CPU.io.addr_ram.asUInt,\n\tdata    = areaCPU.CPU.io.dout_ram\n)\n\nROM.write(\n\tenable  = progDataValid,\n\taddress = progCounter.resized,\n\tdata    = progData.asBits\n)\n\nval readValid = !areaCPU.CPU.io.we_ram\nCPU.io.din_ram := RAM.readSync(\n\tenable = readValid,\n\taddress = CPU.io.addr_ram.asUInt\n)\n\nCPU.io.din_instr := ROM.readSync(\n\taddress = CPU.io.addr_instr.asUInt.resized\n)<\/pre>\n\n\n\n<p>All peripherals are memory mapped, for now, all memory above address 896 is reserved for peripherals. The UART peripheral is made using the existing <a href=\"https:\/\/spinalhdl.github.io\/SpinalDoc-RTD\/SpinalHDL\/Libraries\/Com\/uart.html\">UART library <\/a>in Spinal and looks like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val uart_readValid, uart_read, uart_writeValid, uart_write, uart_writeDone = Reg(Bits(8 bits)) init(\"00000000\")\nval uartCtrlConfig = UartCtrlGenerics(\n  dataWidthMax = 8,\n  clockDividerWidth = 16,\n  preSamplingSize = 1,\n  samplingSize = 5,\n  postSamplingSize = 2)\nval uartCtrl = new UartCtrl(uartCtrlConfig)\nuartCtrl.io.config.clockDivider := 156  \/\/12Mhz clock, 9600BAUD\nuartCtrl.io.config.frame.dataLength := 7  \/\/8 bits\nuartCtrl.io.config.frame.parity := UartParityType.NONE\nuartCtrl.io.config.frame.stop := UartStopType.ONE\n\nuartCtrl.io.write.valid := uart_writeValid.asBool\nuartCtrl.io.write.payload := uart_write\n\nuartCtrl.io.uart &lt;> io.uart\n\nuart_readValid := uartCtrl.io.read.valid.asBits.resized\nuart_read := uartCtrl.io.read.payload\n\nio.din_ram := 0\n\nwhen(uartCtrl.io.write.ready){\n  uart_writeDone := 1\n}\n\nwhen(io.we_ram){\n  when(io.addr_ram === \"d907\"){\n    uart_writeDone := io.dout_ram\n  }.elsewhen(io.addr_ram === \"d908\"){\n    uart_write := io.dout_ram\n  }.elsewhen(io.addr_ram === \"d909\"){\n    uart_writeValid := io.dout_ram\n  }\n}.otherwise{          \n  when(io.addr_ram === \"d905\") {\n    io.din_ram := uart_readValid\n  }.elsewhen(io.addr_ram === \"d906\"){\n    io.din_ram := uart_read\n  }.elsewhen(io.addr_ram === \"d907\"){\n    io.din_ram := uart_writeDone\n  }<\/pre>\n\n\n\n<p>Most of it is setting up the UART library and decoding reads\/writes from memory to the UART registers. The other 2 peripherals, a Timer and GPIO are setup in a similar way. In the end, 2 pages of code, 132 lines, are needed for a GPIO, Timer and a UART peripheral, a lot more compact then a traditional HDL. The full code for the SoC can be found on my <a href=\"https:\/\/github.com\/riktw\/OPCSH\">github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous blog I wrote about a one page CPU in SpinalHDL. But just a CPU is a bit boring, time to turn it into a full System on Chip by adding memory, peripherals and even a UART bootloader. One of the great things of Spinal is the existing libraries, making adding some peripherals [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-557","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Turning a CPU into a SoC - jaeblog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/justanotherelectronicsblog.com\/?p=557\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Turning a CPU into a SoC - jaeblog\" \/>\n<meta property=\"og:description\" content=\"In my previous blog I wrote about a one page CPU in SpinalHDL. But just a CPU is a bit boring, time to turn it into a full System on Chip by adding memory, peripherals and even a UART bootloader. One of the great things of Spinal is the existing libraries, making adding some peripherals [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/justanotherelectronicsblog.com\/?p=557\" \/>\n<meta property=\"og:site_name\" content=\"jaeblog\" \/>\n<meta property=\"article:published_time\" content=\"2019-05-05T13:40:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-05-05T13:40:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg\" \/>\n<meta name=\"author\" content=\"riktw\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"riktw\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#article\",\"isPartOf\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557\"},\"author\":{\"name\":\"riktw\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/#\/schema\/person\/d77e39721321c4a472b49909a8f1982b\"},\"headline\":\"Turning a CPU into a SoC\",\"datePublished\":\"2019-05-05T13:40:25+00:00\",\"dateModified\":\"2019-05-05T13:40:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557\"},\"wordCount\":273,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage\"},\"thumbnailUrl\":\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/justanotherelectronicsblog.com\/?p=557#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557\",\"url\":\"https:\/\/justanotherelectronicsblog.com\/?p=557\",\"name\":\"Turning a CPU into a SoC - jaeblog\",\"isPartOf\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage\"},\"image\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage\"},\"thumbnailUrl\":\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg\",\"datePublished\":\"2019-05-05T13:40:25+00:00\",\"dateModified\":\"2019-05-05T13:40:27+00:00\",\"author\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/#\/schema\/person\/d77e39721321c4a472b49909a8f1982b\"},\"breadcrumb\":{\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/justanotherelectronicsblog.com\/?p=557\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage\",\"url\":\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg\",\"contentUrl\":\"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg\",\"width\":764,\"height\":662},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/?p=557#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/justanotherelectronicsblog.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Turning a CPU into a SoC\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/#website\",\"url\":\"https:\/\/justanotherelectronicsblog.com\/\",\"name\":\"jaeblog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/justanotherelectronicsblog.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/justanotherelectronicsblog.com\/#\/schema\/person\/d77e39721321c4a472b49909a8f1982b\",\"name\":\"riktw\",\"url\":\"https:\/\/justanotherelectronicsblog.com\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Turning a CPU into a SoC - jaeblog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/justanotherelectronicsblog.com\/?p=557","og_locale":"en_US","og_type":"article","og_title":"Turning a CPU into a SoC - jaeblog","og_description":"In my previous blog I wrote about a one page CPU in SpinalHDL. But just a CPU is a bit boring, time to turn it into a full System on Chip by adding memory, peripherals and even a UART bootloader. One of the great things of Spinal is the existing libraries, making adding some peripherals [&hellip;]","og_url":"https:\/\/justanotherelectronicsblog.com\/?p=557","og_site_name":"jaeblog","article_published_time":"2019-05-05T13:40:25+00:00","article_modified_time":"2019-05-05T13:40:27+00:00","og_image":[{"url":"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg","type":"","width":"","height":""}],"author":"riktw","twitter_card":"summary_large_image","twitter_misc":{"Written by":"riktw","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#article","isPartOf":{"@id":"https:\/\/justanotherelectronicsblog.com\/?p=557"},"author":{"name":"riktw","@id":"https:\/\/justanotherelectronicsblog.com\/#\/schema\/person\/d77e39721321c4a472b49909a8f1982b"},"headline":"Turning a CPU into a SoC","datePublished":"2019-05-05T13:40:25+00:00","dateModified":"2019-05-05T13:40:27+00:00","mainEntityOfPage":{"@id":"https:\/\/justanotherelectronicsblog.com\/?p=557"},"wordCount":273,"commentCount":0,"image":{"@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage"},"thumbnailUrl":"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/justanotherelectronicsblog.com\/?p=557#respond"]}]},{"@type":"WebPage","@id":"https:\/\/justanotherelectronicsblog.com\/?p=557","url":"https:\/\/justanotherelectronicsblog.com\/?p=557","name":"Turning a CPU into a SoC - jaeblog","isPartOf":{"@id":"https:\/\/justanotherelectronicsblog.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage"},"image":{"@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage"},"thumbnailUrl":"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg","datePublished":"2019-05-05T13:40:25+00:00","dateModified":"2019-05-05T13:40:27+00:00","author":{"@id":"https:\/\/justanotherelectronicsblog.com\/#\/schema\/person\/d77e39721321c4a472b49909a8f1982b"},"breadcrumb":{"@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/justanotherelectronicsblog.com\/?p=557"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#primaryimage","url":"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg","contentUrl":"https:\/\/justanotherelectronicsblog.com\/wp-content\/uploads\/2019\/05\/unnamed0.jpg","width":764,"height":662},{"@type":"BreadcrumbList","@id":"https:\/\/justanotherelectronicsblog.com\/?p=557#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/justanotherelectronicsblog.com\/"},{"@type":"ListItem","position":2,"name":"Turning a CPU into a SoC"}]},{"@type":"WebSite","@id":"https:\/\/justanotherelectronicsblog.com\/#website","url":"https:\/\/justanotherelectronicsblog.com\/","name":"jaeblog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/justanotherelectronicsblog.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/justanotherelectronicsblog.com\/#\/schema\/person\/d77e39721321c4a472b49909a8f1982b","name":"riktw","url":"https:\/\/justanotherelectronicsblog.com\/?author=1"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=\/wp\/v2\/posts\/557","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=557"}],"version-history":[{"count":4,"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=\/wp\/v2\/posts\/557\/revisions"}],"predecessor-version":[{"id":563,"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=\/wp\/v2\/posts\/557\/revisions\/563"}],"wp:attachment":[{"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=557"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/justanotherelectronicsblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}