-
Data Sheet Documentation Available
11/01/2016 at 23:50 • 0 commentsI've completed enough of the KCP53000 RISC-V CPU's data sheet that I'm satisfied with an announcement here. Take a look and let me know what you think!
I wrote it using Gitbook to be a self-standing document; however, its contents will eventually make its way into the Kestrel-3 User's Guide as well.
Some things I want to work on eventually though:
- I want to convert the processor from an M-mode only CPU to a U-mode only CPU. Revision 1.9 of the privileged ISA spec allows this (even if not overtly). Remember that I started Polaris and the E Emulator back when v1.7 of the privilege spec was available, when a U-mode only implementation simply wasn't possible (and still be standards compliant). I've created a ticket to track this on Github.
- I'd like to augment the data sheet with an example Verilog application of the processor, to show how it'd be used in a real design. I've also created a ticket for this issue as well.
But, for now, it's complete "enough". Let me know what you think!
-
KCP53000 Data Sheet Signal Descriptions
10/16/2016 at 06:19 • 0 commentsI'm making decent progress on the KCP53000 Data Sheet documentation. As I write this, I just finished the Signal Description chapter. Give it a read and let me know what you think.
-
How Did Kestrel Receive its Name?
10/10/2016 at 23:58 • 0 commentsI get asked this a lot, so I figured I'd make a post on it.
Back around 2001 to 2002 or so, long before I had even my first home-brew design working, some of my online friends and I were discussing making a computer built around the 65816 microprocessor, and building it as if Commodore, Apple, Atari, Acorn, and maybe others got together, knowing this was going to be the last 8-bit/16-bit home computer they will ever make, and to come up with their collective last hurrah. Yeah, it was total pie-in-the-sky stuff: a 65816 CPU at 12MHz with 16MB of RAM, video capable of 640x480 resolution with 64K colors, a blitter, tons of sprites, 32-channel PCM audio, 8 expansion slots into which you could plug in things like hard-cards (remember those?!), Ethernet adapters, etc. It was going to be awesome!
Anyway, we needed a name for the project, so I didn't call it "my home-brew computer project" all the time. But, I wanted the name to be marketable (that is, catchy). Commodore, Apple, Atari, Acorn, et. al. all had easy to pronounce names, and no more than three syllables.(If this sounds familiar, yes, it's the same logic I used to stipulate a successful part numbering system for the Kestrel in my previous log.) Eventually, an on-line associate and game software developer named Madgarden suggested, on a whim, Kestrel. I'm not entirely sure why he chose that name, but it has stuck ever since.
And that's how the Kestrel received its name!
But, why Kestrel-3?
OK, since you (never) asked...
Fast forward to 2004, where I finally wire up a 65816 on a cheap Radio Shack (remember them?!) breadboard running at 4MHz, with 32KB of RAM, and a whopping 16 bytes of I/O space. Not even ROM. That took a fair bit of effort to get going as it was, but the proof of concept proved I could do it: I can make the Kestrel.
(I still have my tube of W65C816P-14 DIPs, a pair of W65C22 VIAs, and some 4MHz can oscillators left from those days, if you can believe it. That was back when WDC required a $100 minimum purchase.)
Moving forward again to 2007, I can finally afford my first FPGA development system. This became home to two computer designs. One, the Kestrel as envisioned back in 2001, flopped spectacularly, because I simply didn't have the experience needed to build such a crazy thing. I got flustered, and eventually canned it completely.
Around 2011, I picked it up again, this time taking the approach that I should work on the cores needed to make the Kestrel first, then add the CPU last. I'd use test-driven techniques to build the circuitry (which has never failed me since, BTW). However, bench tests can only go so far; I needed a real CPU to perform integration tests too. So I whipped up a clone of the Steamer-16 CPU from Myron Plichota, and adapted it to my needs, thus making the S16X4 CPU. After integrating this CPU and proving that it worked by pushing raw pixels on the monochrome screen (remember, I was trying to start very simple this time), I moved forward with other components necessary to make a simple computer. Over time, software and hardware accreted organically, and I ended up with a computer that actually worked, and I could call my own. I eventually started giving presentations about this computer on this computer.
At this time, I dubbed it the Kestrel-2, and retroactively re-branded my proof of concept machine the Kestrel-1.
Advance to 2014-2015 time-frame, and now I'm working yet again on another Kestrel incarnation. This one built around a 64-bit RISC-V processor, the KCP53000 (formerly Polaris). I'm reusing as many parts from the Kestrel-2 as I can to build a working 1st generation Kestrel-3 computer; however, rest assured, once this is in place, I'll have not only the platform, but also the experience, needed to finally realize the computer I had in mind back in 2001. Only this time, I'll get there incrementally, slowly, and deliberately; and, not risk having a large up-front and costly design that will inexorably lead to certain failure.
Hope this helps!
-
Polaris CPU Family Needs New ... Number?
10/09/2016 at 03:39 • 2 commentsI just found out that AMD has a GPU named Polaris. This sucks for me. GPUs and CPUs are too close for trademark disambiguation on the basis of design origin or maturity, and AMD has a lot more lawyers than I do (namely, greater than zero). Therefore, I'm looking to pre-emptively avoid a cease and desist from AMD's lawyers for my CPU design.
(The Kestrel Computer Project is no stranger to these things happening; this is not the first time I've had to do a pre-emptive name change. Such is the life of a project with no legal representation or funding.)
This reminds me of when Intel made the decision to adopt the name Pentium instead of market their chips as the 80586. Intel realized that, as long as they tied their architecture to a number, they could not trademark anything about the processor architecture. That was bad for Intel, because it meant competitors like AMD could just implement their own clones and market them as Am586 or some similar part number, with data sheet headings clearly implying Intel compatibility without actually naming Intel or their competitive hardware by name.
I want exactly the opposite for the Kestrel and its chip/core designs. I want wide-spread press, use, cloning, forking, etc. Thus, I think the Kestrel's family of cores need part numbers, not names.
(I know; it's totally arbitrary. But, still...)
All of the nicely marketable numbers are taken though. You know the numbers: those that resonate and leave a mental imprint in your mind of how awesome they were. I'm talking about the 1802, 6502, 65816, 680x0, 6800, 6809, Z80, 9900, 99000, etc. Even Sifive, Inc. is using the technique, with their U500 and E300 products.
Notice a pattern? All of those numbers just roll off the tongue, because, at least in American English, they have between 3 and 5 syllables. Eighteen-oh-two (4), Sixty-five-oh-two (5), Six five eight one six (5), sixty-eight thousand (4), and so forth. It seems that any family number the Kestrel hardware ends up with should similarly have such syllabic constraints. As far as I can tell, only the family name..er..number needs to meet this constraint. Example: neither Motorola's 68882 nor Commodore's 6561 number complies (7 and 6 syllables, respectively, again assuming American English).
I'd love feedback on this; what number should I use to identify a family of Kestrel-related FPGA cores? Remember that the family includes not only better CPUs, but also peripherals as well. Some cores I have so far:
- S16X4A 16-bit MISC processor (powers Kestrel-2)
- KIA, the Keyboard Interface Adapter for the Kestrel-2
- GPIA, the General Purpose Interface Adapter for the Kestrel-2
- MGIA, the Monochrome Graphics Interface Adapter (640x200) for the Kestrel-2
- S64X7A 64-bit MISC Forth processor
- Polaris 64-bit RISC-V (RV64IS ISA) processor
I have plans to make the following:
- KIA-II, a slightly enhanced KIA for the Kestrel-3
- GPIA-II, a 64-bit refresh of the GPIA, also for the Kestrel-3
- MGIA-II, a 640x480 update of the MGIA, also for the Kestrel-3
- CGIA, the Configurable Graphics Interface Adapter, also for the Kestrel-3, eventually to replace the MGIA-II.
- An asynchronous RAM interface for first-generation Kestrel-3 designs.
- A synchronous DRAM interface for next-generation designs.
Longer term, I am going to consider a variety of updates to the processor too, including more aggressive pipelining; M, F, and D ISA extensions, MMU support, caching, etc. (At least up until the point that porting Rocket core directly becomes feasible.) If I stuck with names, then Polaris-II, Polaris-III, etc. are natural names for the enhancements. But, if I don't have names?
What do you think? Let me know in comments. Thanks!
-
Polaris CPU Released!!
10/08/2016 at 18:37 • 0 commentsIt's crude. It's undocumented. It's untested (except for benchtests). But it's finally here!
The Polaris 64-bit RISC-V CPU has finally landed, and now resides in its official repository on Github.
Next steps include the obvious things (in no particular order):
- Documentation for RISC-V Workshop and SVFIG Conferences.
- Automated tests for continuous integration/deployment.
- Integration onto FPGA for hardware demonstration.
- More that I probably haven't thought of or have forgotten.
-
Plan for Supporting CSRs
10/03/2016 at 17:51 • 0 commentsI'm currently planning on not providing any built-in CSRs to the Polaris core. At all. Rather, I'm planning on providing access to CSRs via an external bus. This allows Polaris to focus exclusively on its core competency (instruction execution).
The CSR bus would look something like this sketch:
- CADR_O[11:0] -- CSR address bus. This reflects bits 31:20 of the current CPU instruction.
- CV_I -- CSR Valid. True iff the address on the CADR_O bus maps to a supported CSR register. If Polaris executes any CSR-instruction and CV_I is false, then an illegal instruction trap happens. Note that CV_I must be valid within the same clock cycle that CADR_O goes valid. That means asynchronous decoding logic.
- CDAT_O[63:0] -- CSR data bus. The value on this bus is to be written to the addressed CSR if CWE_O is asserted in the same cycle.
- CDAT_I[63:0] -- CSR data bus. The value appearing on this bus is the current value of the addressed CSR if COE_O is asserted in the same cycle.
- CWE_O -- Write Enable. Asserted if Rs1/zimm != 0 in the RISC-V CSRR* instruction. This enables write-back to the CSR, and therefore enables any write-triggered behavior associated with the addressed CSR.
- COE_O -- Output Enable. Asserted if Rd != 0 in the RISC-V CSRR* instruction. This enables reading from the CSR, and therefore enables any read-triggered behavior associated with the addressed CSR.
I envision the CSRs will be clocked using the same clock as the Polaris core. Except in the case of CSRRW, one cannot read and write to the CSR in the same clock cycle. So, the Polaris core will need to spread CSR access out over several cycles.
Trap Vectors and Other Configuration Settings
When Polaris gains the capacity for interrupts, how will the value of mtvec be communicated, since mtvec sits in a CSR? In all likelihood, I'll just provide configuration ports on Polaris (e.g., MTVEC_I[63:2]), to which the CSRs feed back into, and which must be valid when any ERR_I or IRQ_I signal is asserted. So, altering mtvec will simply alter a bunch of bits that drive these configuration ports.
Privilege Levels
How will I handle privilege levels going forward? In all likelihood, I won't. Polaris doesn't appear to have or need any privilege-sensitive instructions, and none are currently defined in RV64G as far as I can tell (note that RV64IS is a proper subset of RV64G). Thus, privilege enforcement can be off-loaded to logic external from the Polaris core itself.
In exchange, Polaris core does need to expose control signals which will help outside logic deal with possible privilege-sensitive semantics. For example, the FENCE and FENCE.I instructions both assert a FENCE_O signal on the bus. When a trap occurs (e.g., illegal instruction), TRAP_O asserts, letting external logic know that a transition to machine-mode is required, etc.
This technique is not unproven; prior art exists. The 68010 CPU was built to handle architectural enhancements of this nature. And, of course, the 65816 CPU also provides similar capabilities, allowing one to start with an ultra-basic expanded 6502-like CPU, and to that you can bolt on virtual memory (thanks to the ABORT# signal), different privilege modes (thanks to VP# to indicate when a system call [BRK or COP] or interrupt is being processed), etc. IP built around the 65816 core can provide distinctly non-6502-like semantics; for example the 65265 microcontroller provides a lot more than your standard RESET, IRQ, and NMI interrupt vectors.
Summary
My plans for Polaris might change given the current implementation's flexibility. If this CSR interface works out as I envision, I might dive even further in this direction. Polaris might have a future as a modular RISC-V core, which stands in stark isolation from all the other "kitchen-sink included" cores I see on Github, where configuration is handled with Verilog "`define" settings instead of through module composition.
-
Polaris CPU Almost at First Milestone
10/03/2016 at 05:59 • 0 commentsPolaris CPU now supports all RV64I instructions, with the following exceptions:
- RDTIME, RDINSTRET, and friends, because these are actually specializations of the CSRRS instruction. I don't yet have CSR support implemented.
- ECALL and EBREAK, because I don't yet have traps implemented. I need access to CSRs in order to configure and respond to traps.
- WFI and MRET, because I again lack CSR support.
- FENCE.VM, because this doesn't make sense on a CPU lacking an MMU.
As long as you do not need interrupts, and you can guarantee you'll never execute an illegal instruction, and that all memory accesses will terminate, then you can theoretically use Polaris now to run real RISC-V user-level code.
The CPU synthesizes, and is small enough to fit on an iCE40HX4K part (!!), albeit without Wishbone interface to memory or I/O.
I know I expected to overlap instruction fetch with as many execution cycles as I could, thus comparing the design to the 6502. However, in practice, it was easier for debugging purposes to not do this: fetching and execution occur on distinct clock cycles. For this reason, performance is even slower still than what I had originally wanted; however, given fast enough memory, we're still looking at a performance that compares well with a Z80. Sorry about that; I figured it'd be better to get something running first, then optimize the microarchitecture later.
As it is, though, the CPU weighs in at under 2400 logic cells, making it small enough for synthesis onto an iCE40HX-4K part. As far as I'm aware, this is the world's smallest 64-bit RISC-V processor.
Native Buses
The Polaris native bus is a distortion of the Wishbone bus, optimized for the needs of the RISC execution engine. The address and data buses as well as ACK_I, ERR_I, etc. all work the same; where things differ are in the control buses.
Instead of SEL_O to select which byte-lanes to place data on, it uses SIZ_O instead. The SIZ_O signal uses two bits to indicate how big the data transfer is for this cycle:
- 00 = byte (8-bits)
- 01 = half-word (16-bits)
- 10 = word (32-bits)
- 11 = double-word (64-bits)
When reading a value smaller than 64-bits, external logic is expected to properly align and sign-extend the value read. For example, all bytes read must appear on DAT_I[7:0], all half-words must appear on DAT_I[15:0], and all words on DAT_I[31:0]. The upper bits (DAT_I[63:8], DAT_I[63:16], and DAT_I[63:32], respectively) must represent the proper sign- or zero-extension, depending on the state of another bus control signal: SIGNED_O. Note that this signal is defined only when WE_O is negated. For this to work at all, obviously, low address bits are exposed as well. It's entirely possible to perform a 64-bit fetch on an odd address; external logic must raise ERR_I if it doesn't want to bother with handling non-aligned accesses.
Put another way, the RISC core only reads and writes whole 64-bit words, even if you're executing a LB or SH instruction. It's up to the external bus bridge to make those instructions behave appropriately. As you can imagine, this bus is not intended for general consumption. Eventually, I'll include a trusted Wishbone bridge with the core so users don't have to deal with this ultra-low-level stuff.
Polaris also implements two buses: a reduced bus for instruction fetch, and a full bus for general data I/O. They are different sizes as well; the instruction fetch bus is 32-bits wide, while the data I/O bus requires 64-bits. Both support 64-bit address spaces, though. This lets you implement a Harvard architecture design if you wanted; however, you'll need a mixed-size dual-port Wishbone bus arbiter if you want to interface the CPU to a common, Von Neumann bus architecture.
Next Steps
CSRs. My immediate problem is figuring out how I want to handle CSR support. According to the privilege specification, I must support no fewer than 29 (!!) M-mode CSRs. Most are read-only and constant, some are read-write. However, they're going to be sparsely placed in a CSR address space of 4096 registers, which will consume a lot more FPGA logic cells than I'd like. I estimate another 300 or so DFFs just for storage overhead alone.
All of the CSR accessors are read-modify-write instructions, and they have inconvenient edge cases involving the X0 register when used as either a source or destination. This adds a fair amount of complexity to the instruction decoding logic. Thankfully, none of the M-mode CSRs have read- or write-triggered behaviors, so I might be able to get away with avoiding this edge-case logic.
I was hoping to have CSR support finished today, but this turned out to be a much bigger problem than I had anticipated.
Interrupts. Once CSR support is in place, then I need to add support for illegal instruction traps and for external interrupts. These ought to be fairly easy to get working once I've completed the heavy lifting for the CSRs.
Bus Bridges. After I finish support for interrupts, the next step is to couple the CPU to actual memory and get it to run a real program on hopefully real hardware. To do this, I'll need a Wishbone bus bridge as discussed above. A mixed size, quad-port bridge will be needed to make anything even resembling the functionality of a Kestrel-2: a 32-bit I-bus and a 64-bit D-bus to the CPU, a 16-bit IO-bus to talk to devices like KIA and GPIA, and a 16-bit X-bus to talk to eXternal asynchronous RAM.
Documentation. I need to document this core thoroughly, along with any support cores, since I've decided to submit the microarchitecture for a poster session at the 5th RISC-V Workshop in November. I'm not sure if I'll make it in; however, if I do, I need to be ready with at least a preliminary data sheet and a poster with its architectural block diagram.
-
Polaris CPU is Alive AT LAST!
09/25/2016 at 03:58 • 2 commentsI'm currently trying to re-implement the Polaris CPU once more (as I said I would in a previous log), using a combination of hand-written Verilog and generated code from SMG, codeveloped in a step-by-step fashion. You might not be able to get much information from the diagnostic trace below, but you might be able to discern that IADR is the instruction address bus (specifically, the lowest 32-bits of it). Notice that the core fetches an instruction from $FF...FFFF00, and four cycles later, attempts another fetch at $FF..FFFF04. Polaris just executed its first ever RISC-V instruction!! (BTW, it was a NOP: ADDI X0, X0, 0 in case you were wondering).
@S SCENARIO 1 (16'h0001) @D -TIME- CLK ... ISIZ IADR JAM @D 310 1 ... 00 00000000 1 @D 320 0 ... 00 00000000 1 @D 340 1 ... 00 00000000 0 @D 360 0 ... 00 00000000 0 @D 380 1 ... 10 ffffff00 0 @D 400 0 ... 10 ffffff00 0 @D 420 1 ... 00 00000000 0 @D 440 0 ... 00 00000000 0 @D 460 1 ... 00 00000000 0 @D 480 0 ... 00 00000000 0 @D 500 1 ... 00 00000000 0 @D 520 0 ... 00 00000000 0 @D 540 1 ... 10 ffffff04 0
I'm excited almost to tears, as followers of this project will probably guess if they paid attention to my logs to date. Polaris implementation has given me nothing but heart-ache for almost a full year. To finally have come across a development approach that actually works (made possible thanks to the SMG state machine to Verilog generator tool I also wrote) makes me so very happy, you have no idea.
Back to hacking; I need to implement other ALU operations besides ADDI before I declare this night a complete victory.
-
I'm still alive!
09/12/2016 at 19:00 • 0 commentsAgenda.
- Kestrel Project Health.
- CPU Plans.
Kestrel Project Health. Just wanted to keep everyone up to date with my progress, which is to say, just to let everyone know that I'm still alive. I've not had any progress recently due to a perfect storm of health issues, work, and family obligations.
Because of so many interruptions in my life at present, I've utterly given up on getting something working by the next RISC-V workshop. It's just not going to happen. The Kestrel CPU will be done "when it's done."
Polaris CPU Plans. I am thinking of starting the CPU design over from scratch, yet again. Hey, at least I'm homing in on a design I'm actually happy with! Using SMG and what I already have developed so far, I think starting the CPU over from scratch might be the best thing.
I am trying to work through a design which I wrote using SMG almost a month ago, primarily to see what it'd be like using SMG in my development process. I'm pretty pleased with the result; however, there are a lot of undefined signals and such as a result of human error. Between the size of the design and some much needed functionality in SMG itself, I find the design is too big to debug by hand after the fact. [i]SMG is so simple to use and express a design in, you're tempted to just let the design flow in a single session.[/i] [b]Resist this urge.[/b] A better notation is nice, but it's still programming. Treat the process and the tool with respect.
My thoughts are that if I just [i]freeze[/i] what I currently have, start over from scratch and incrementally build the processor up one logical facility at a time, I will have a better chance of spotting errors in my overall thinking, to say nothing of better motivation due to more frequent wins (even if each individual win is smaller as a result).
-
S64X7 MISC Core Update
08/17/2016 at 17:21 • 0 commentsI have two updates in one here. The first deals with the relationship of my S64X7 CPU to the iCE40-HX8K and -HX4K parts, and a small side-project that I think will help hasten the pace of development overall (regardless of hardware platform I use).
S64X7 Progress Update
My MISC CPU is essentially done. Only a few tweaks need be applied, but it is not only Turing complete, but synthesis shows it's fully operational as a Forth CPU sans interrupts right now. I'm debating whether or not I even need interrupt support at this level, since it's intended task is to emulate the RV64I instruction set.
The bad thing is, it's still disturbingly large for an iCE40 device, coming in at about 6400 LUTs (rounded) best-case after hand-tweaking. It fits in an 8K device, but only just barely. It definitely won't fit on a 4K device (>3000 LUTs too big), per Lattice's iCE40 family documentation. Some people have said that 4Ks are really rebranded 8Ks, but honestly, a semiconductor vendor doesn't bin parts like that unless there's something wrong internally on the chip. I'll trust iCE40's specifications for now.
The size of the part is still a concern for 8K devices though; with it taking up 92% of the fabric's resources, there's not a whole lot of room for a Wishbone 64-bit-to-16-bit bus bridge. I don't think I can pull it off. Not with my skills, at least.
I think I'm going to give up on the use of iCE40 FPGAs for now. The Kestrel Project seems like it's just too ambitious for such a small FPGA. It would certainly work out if I had implemented a 16-bit CPU (perhaps a clone of the 65816), but 64-bits is just tasking these parts too much.
Side Project: SMG
One of the reasons why I had to start the RISC-V implementation over many times is I'd get to a certain point and then lose intellectual control over the project. I'd run into such dead-ends as getting instruction fetching working, and getting it to time the instruction execution for, say, ADDI X0, X0, 0 working correctly, but then I'd lose track of how everything else fits together. I'd also run into problems programming the state machines by hand in Verilog.
So, I decided to write myself a small tool which I think will help me in this endeavor. I called it SMG, for State Machine Generator. The name isn't indicative of what it actually does, but there's no question that it contributes to that task, and so it's the best name I could think of.
Not only will it help with designing whatever CPU I end up using, but its applicable to other parts of the Kestrel Project as well, since it covers a large number of applications of FPGA-based digital logic designs.
It takes input in a more tabular format, such as this 3-bit Gray counter example:
(do (put next bus-spec "[2:0]") [[on [[ctr 3'b000] ~reset] [next 3'b001] [odd 0]] [on [[ctr 3'b001] ~reset] [next 3'b011] [odd 1]] [on [[ctr 3'b011] ~reset] [next 3'b010] [odd 0]] [on [[ctr 3'b010] ~reset] [next 3'b110] [odd 1]] [on [[ctr 3'b110] ~reset] [next 3'b111] [odd 0]] [on [[ctr 3'b111] ~reset] [next 3'b101] [odd 1]] [on [[ctr 3'b101] ~reset] [next 3'b100] [odd 0]] [on [[ctr 3'b100] ~reset] [next 3'b000] [odd 1]] [on [reset] [next 3'b000]]] )
The result is something like this:
wire R1287 = ( ctr == 3'b000 ) & ~(|reset) ; wire R1288 = ( ctr == 3'b001 ) & ~(|reset) ; wire R1289 = ( ctr == 3'b011 ) & ~(|reset) ; wire R1290 = ( ctr == 3'b010 ) & ~(|reset) ; wire R1291 = ( ctr == 3'b110 ) & ~(|reset) ; wire R1292 = ( ctr == 3'b111 ) & ~(|reset) ; wire R1293 = ( ctr == 3'b101 ) & ~(|reset) ; wire R1294 = ( ctr == 3'b100 ) & ~(|reset) ; wire R1295 = (|reset) ; wire [2:0] out1296 = R1287 ? 3'b001 : 0 ; wire out1297 = R1287 ? 0 : 0 ; wire [2:0] out1298 = R1288 ? 3'b011 : 0 ; wire out1299 = R1288 ? 1 : 0 ; wire [2:0] out1300 = R1289 ? 3'b010 : 0 ; wire out1301 = R1289 ? 0 : 0 ; wire [2:0] out1302 = R1290 ? 3'b110 : 0 ; wire out1303 = R1290 ? 1 : 0 ; wire [2:0] out1304 = R1291 ? 3'b111 : 0 ; wire out1305 = R1291 ? 0 : 0 ; wire [2:0] out1306 = R1292 ? 3'b101 : 0 ; wire out1307 = R1292 ? 1 : 0 ; wire [2:0] out1308 = R1293 ? 3'b100 : 0 ; wire out1309 = R1293 ? 0 : 0 ; wire [2:0] out1310 = R1294 ? 3'b000 : 0 ; wire out1311 = R1294 ? 1 : 0 ; wire [2:0] out1312 = R1295 ? 3'b000 : 0 ; assign odd = out1311|out1309|out1307|out1305|out1303|out1301|out1299|out1297; assign next = out1312|out1310|out1308|out1306|out1304|out1302|out1300|out1298|out1296;
You'll notice that I deliberately avoid using case or casez statements. These statements have two problems which impedes my use of Verilog for building CPUs and other components:
First, it builds its decoders using priority encoder logic. This uses more resources than I intend. A simple AND-based pattern-matcher is what I would strongly prefer, as what you'd find in a PLA circuit.
Second, support for multi-hot firings is severely limited and non-portable. Verilog really, really wants single-hot handling of cases. This, again, is not conducive to reusing already written minterms. (Clearly, the simplistic example I gave above does not illustrate this will at all.) One can see the value of this by studying how the 6502 manages to overlap instruction fetch with instruction execution, and how this interacts with its address mode handling. The CPU has only 3510 transistors, so they must be doing something right.
My hope is that SMG will let me develop Verilog modules which are measurably (if not significantly) smaller.
SMG is still not quite ready for prime-time use, but it's coming along quite nicely. I plan on reworking the instruction decode logic for the S64X7 CPU as a first real-world test. If it passes the current bench tests, I'll be ecstatic and quite hopeful for future core development.