{"id":20418884,"url":"https://github.com/sehugg/nanoasm","last_synced_at":"2025-04-12T17:40:24.837Z","repository":{"id":139692101,"uuid":"188624301","full_name":"sehugg/nanoasm","owner":"sehugg","description":"a tiny configurable assembler for Verilog projects","archived":false,"fork":false,"pushed_at":"2021-07-12T23:16:02.000Z","size":28,"stargazers_count":11,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-26T12:01:42.664Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sehugg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-26T00:21:42.000Z","updated_at":"2025-02-04T20:18:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"7306c105-8cf0-4e07-8a55-7669fe44ff9a","html_url":"https://github.com/sehugg/nanoasm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sehugg%2Fnanoasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sehugg%2Fnanoasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sehugg%2Fnanoasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sehugg%2Fnanoasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sehugg","download_url":"https://codeload.github.com/sehugg/nanoasm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248607325,"owners_count":21132512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T06:35:10.966Z","updated_at":"2025-04-12T17:40:24.829Z","avatar_url":"https://github.com/sehugg.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NANOASM\n\nA tiny configurable assembler for Verilog projects, as described in the book \"[Designing Video Game Hardware in Verilog](https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?ie=UTF8\u0026camp=1789\u0026creative=9325\u0026creativeASIN=1728619440\u0026linkCode=as2\u0026tag=pzp-20\u0026linkId=c149f6365c0a676065eb6d7c5f8dd6ae)\" and integrated into the [8bitworkshop](https://8bitworkshop.com/) online Verilog IDE.\n\n## Installation\n\n    npm i\n\n## Usage\n\n    node src/asmmain.js \u003cconfig.json\u003e \u003cfile.asm\u003e\n\nOutput binary is hex format, one line per word, compatible with Verilog's\n`$readmemh` command.\n\n## Examples\n\n    cd examples\n    make\n\n## Configuration\n\nNANOASM can translate custom assembly language for Verilog CPUs.\nThe CPU's language is defined in a a JSON configuration file.\n\nOur assembler's configuration format has a number of rules.\nEach rule has a format that matches a line of assembly code, and a bit pattern that is emitted when matched.\nFor example, this is the rule for the `swapab` instruction:\n\n    {\"fmt\":\"swapab\", \"bits\":[\"10000001\"]},\n\nThe \"fmt\" attribute defines the pattern to be matched, which in this case is just a simple instruction without any operands.\n\nIf the rule is matched, the \"bits\" attribute defines the machine code to be emitted.\nThis can be a combination of binary constants and variables.\nHere we just emit the bits `10000001` -- i.e., the byte `$81`.\n\nLet's say we want to match the following format, `sta \u003cn\u003e` where `\u003cn\u003e` is a variable 4-bit operand:\n\n\tsta [0-15]\t; 4-bit constant\n\nWe can specify different types of variables in the \\textbf{vars} section of the configuration file.\nFor example, this defines a 4-bit variable named `const4`:\n\n    \"const4\":{\"bits\":4}\n\nThe assembler rules are big-endian by default (most significant bits first) so if\nyou need constants larger than a single machine word, set the \"endian\"\nproperty:\n\n    \"abs16\":{\"bits\":16,\"endian\":\"little\"}\n\nTo include a variable in a rule, prefix the variable's name with a tilde (\\textasciitilde).\nFor example, our `sta` rule takes one `~const4` variable:\n\n    {\"fmt\":\"sta ~const4\", \"bits\":[\"1001\",0]},\n\nWe also have to include the value of the variable in the instruction encoding.\nTo do this, we put an integer into the \"bits\" array -- 0 for the first variable, 1 for the second, etc.\n\nAn example: The assembler is given the instruction `sta 15`.\nIt matches the rule `sta ~const4`, and assigns 15 to the first variable slot.\nIt then outputs the the bits `1001` and then the 4-bit value 15, or `1111`.\nThe final opcode is `10011111` or `$9f`.\n\nInstead of a single integer index, you can emit a slice of bits.\nThis comes in handy for instruction sets where values are not contiguous,\nfor example RISC-V:\n\n    // for argument 1, take 7 bits starting at index 5, then 5 bits starting\n    // at index 0\n    // {a = argument index, b = bit index, n = number of bits}\n    {\"fmt\":\"sb ~reg,~imm12(~reg)\",   \"bits\":[{\"a\":1,\"b\":5,\"n\":7},2,0,\"000\",{\"a\":1,\"b\":0,\"n\":5},\"0100011\"]},\n\n\n## Tokens\n\nVariables can also be defined by tokens.\nFor example, the following rule defines a variable `reg` with four possible values -- `a`, `b`, `ip`, or `none`, encoded as two bits:\n\n    \"reg\":{\"bits\":2, \"toks\":[\"a\", \"b\", \"ip\", \"none\"]},\n\nHere's an example of a rule that uses it:\n\n    {\"fmt\":\"mov ~reg,[b]\", \"bits\":[\"11\",0,\"1011\"]},\n\nWhen decoding `mov a,[b]`, the assembler sees that `a` is the first token in the variable, and substitutes the bit pattern `00`.\nThe final bit pattern is `11` `00` `1011` which makes a full byte.\n\nMore complex instructions are possible, by using multiple variables in a single rule:\n\n    {\"fmt\":\"~binop ~reg,#~imm8\", \"bits\":[\"01\",1,\"1\",0,2]},\n\nIn this rule, `binop`, `reg`, and `imm8` (2) are variables, identified by the integers 0, 1, and 2.\n`add b,#123` is an example of a matching instruction.\nThis rule emits an opcode 16 bits (two bytes) long.\n\n## Directives\n\nNANOASM supports these directives:\n\n`.arch \u003carch\u003e` -- Required. Loads the file `\u003carch\u003e.json` and configures the assembler.\n\n`.org \u003caddress\u003e` -- The start address of the ROM, as seen by the CPU.\n\n`.len \u003clength\u003e` -- The length of the ROM file output by the assembler.\n\n`.width \u003cvalue\u003e` -- Specify the size in bits of an machine word. Default = 8.\n\n`.define \u003clabel\u003e \u003cvalue\u003e` -- Define a label with a given numeric value.\n\n`.data $aa $bb ...` -- Includes raw data in the output.\n\n`.string .....` -- Converts a string to machine words, then includes it in the output.\n\n`.align \u003cvalue\u003e` -- Align the current IP to a multiple of `\u003cvalue\u003e`.\n\n# LICENSE\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsehugg%2Fnanoasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsehugg%2Fnanoasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsehugg%2Fnanoasm/lists"}