📜 ⬆️ ⬇️

Microcontroller DIY

Trying to master the controllers and already possessing programming skills in FPGAs, a bad thought occurred to me. She came, knocked and entered. All those who come to bad thoughts, and who are interested in how others cope with this phenomenon, are dedicated.

There was an idea to draw your controller, not limited by the number of peripherals, RAM, and other parameters, except FPGA capacity. Let's say the controller contains 5 UARTs, and the sixth is badly needed, you have to dodge. And why, if you can just click the mouse and add the necessary? Or vice versa, the problem is well solved on five controllers with a width of 5, 32, 20, 32 and 20 with an unpredictable number of communication lines between them. It is a pity to use five 32 dischargers, the resource is always a pity, and to combine two subtasks per core is ugly or something.

Interrupt response time in controllers is quite large. Yes, the interrupt controller monitors the inputs (for some reason limited in number), regardless of the core. But before you start executing the program code for handling interrupts, say, read the port, you need to save the general-purpose registers and then restore them. And this is not one clock cycle to empty from the point of view of the logic of the program, rewriting registers to the stack and returning the same values ​​back. It certainly fits into the concept of real time, but you can also do it instantly: the code with low priority was executed, at the very next clock because of urgent need, a high-priority timer interrupt will be executed, and after the clock the code for processing the external data flow is executed, because absolutely everything is necessary quickly.

Of course, all these problems are contrived and solved easily and simply. But a bad thought does not seek such solutions, it just wanders in the crowded space of consciousness and pushes to make a non-standard. And, if a young engineer has a vacation, then forgive his wife and children, but dad does not “sit at the computer again,” but grows professionally. Moreover, sometimes you want to perform not your invented tasks, but your own ones, completely yours.
')
image

Fig. 1. Timers. Add as you want. Pay attention to the grammatical error. It's a shame, but you don't want to install Builder for recompilation.

Let me introduce you to the controller, whose architecture is not so different from all the others, rather, it is not accepted for service. The list of readings before the beginning of the works of literature has long been forgotten, the thoughts of many people from different computer eras have been used, forgive me, my forgotten teachers. But you do not have to disown me. Yes, and it did not carry the money, so nothing to share.

I’ll say right away that the controller took place, flashed into Spartans of all generations and successfully works in the CIS and in one Baltic country. Now a lot would have been done differently, but any changes to me are already lazy and what happened, happened. And that's what happened.

- Controller resolution from 1 to 32, with or without a sign. (I don’t remember whether I checked the work at small digits). An additional code is used.
- The number of input / output ports is not limited, the bit depth is limited by the bit depth of the kernel.
- The number of timers is also unlimited. For each timer, you can set your interrupt handler.
- Interrupt handler with an infinite number of inputs, each input has a priority from 0 to 99 (limited by the reason "and so a large number"). Ability to disable all interrupts or low priority only.
- The number of serial ports of the UART type is unlimited, the bit width is limited by the core bit depth.
- The frequency divider is made badly and incorrectly, but regularly produces any frequency for any periphery or just outside the controller.
- Coprocessor. About him below.

That is, we have a controller that supports the basic operations of arithmetic and other changes of bits in words (plus, minus, shift, bitwise logic ...). He also accesses the internal memory and stores the program code in the same way. The memory is used block, it is the one that is platform-dependent and in the program settings it is necessary to indicate which chip will be the carrier of the controller. All operations in any direction of action are performed in one cycle, it may not always be good, but it simplified the design of the architecture. The exception is the integer divider, whose functions are implemented in the coprocessor, the division is performed slowly but surely. The division algorithm was chosen as the simplest - bitwise.

I would like to tell you about the command code, but I don’t remember what it consists of. Based on the principle of “not using what is not used,” even the length of the command code is not a constant value, much less its contents. Let's say if there are 14 instructions in the compiled program, then each instruction is encoded with 4 bits, if 18 instructions are used, the fifth bit is allocated. Plus a bit is added to each command, if it is 0, then the command is single, if 1 is double, or vice versa, this is not important. Double command is needed for operations that contain the address of the RAM or ROM. Add to this the fact that the bus addresses also have non-constant lengths, and we get a complete mess in the command code, there’s no point in considering it as a disassembler, just like the assembler in this controller.

The fort is the language that allowed me to realize these strange ideas. The fort is simple and low-level. Writing a compiler of this language is a pleasure. Well, of course, all language constructs are not supported, only the basic ones for sending data and changing them.

image
Fig. 2. The leadership is quite modest. Immodesty is not written.

image
Fig. 3. The second part of the manual. I do not know why, but the window can not be expanded. There is also a third part, but absolutely boring.

And, naturally, we have a stack controller. That is, the Fort functions in its natural environment — on the stack, on the hardware stack, and not on a slow software stack. “All for the beat!” - the second motto of the project. The hardware stack allowed to go straight to the execution of data processing commands when switching to a function or calling an interrupt, without the need to save the content of the interrupted process. The “new” data is simply pushed onto the stack from above, the “old” goes into the depths and is well preserved there. Then, the “new” data, having participated in various operations, are safely transferred to the RAM or other places, and the “old” ones are pushed to the top. When returning to the interrupted section of the code, no one will notice anything. The address of the interrupted code is stored in another stack, and the maximum number of interrupted processes depends only on the depth of the Returns stack. This value is configured during compilation, even if it is a “very large number”. Parameters in the function are also passed through the stack.

Stackcpu - this is exactly what the controller is called, for some reason, Latin, although you can also write code in Cyrillic. What I am doing, I will give an example of the function “change_bit_ in_word”:

:___ ___, ____, ____; 


Where: “read_from_port_port”, “change_read_read_from_port_port”, “write_in_ required_ memory_cell” are functions that perform certain actions.

Well, am I not crazy ? I will cite more evidence, the traffic light control program:

  \\main BEGIN  ,  ,  .   …  ,  ,  .   …  ,  ,  .   …  ___,  ,   _.   … 0 UNTIL \  


Well, crazy crazy ? The third principle of the project: "The literary language in the management of electronics!" Although, as practice has shown, writing programs is quite tiresome. For connoisseurs, the Fort will inform you that my compiler perceives the period as a separator, and a comma too. Of course, it is better to use the C language, but the C compiler is too tough for me, and the architecture does not allow the use of third-party compilers.

image
Fig. 4. Development environment with the report of the compiler and linker.

How much capacity does the FPGA take up the controller? But who knows? It all depends on the digit number of the selected periphery, something else, and on the text of the program. The controller will not have a multiplier if it is not found in the program code, or there will be no divider if the programmer does not use it. By programmer, I mean myself, since there are no other programmers of this controller (the principle “do not use those who do not use”). By block memory for data RAM and command ROM: at least two blocks, maximum all block crystal memory.

The maximum frequency of work is calculated only empirically, for a specific architecture. One of my 24-bit controllers did not work at a frequency of 48 Mhz in Spartan2, at a frequency of 40 Mhz it worked. In Spartan6, 32-bit worked on a hundred Mhz. And maybe it will work on a couple hundred, nothing in it is so complicated.

image
Fig. 5. This is the code that the processor will see. Note that one FORTH command is one processor core command — one system clock.

First PS: I’ll mention one coprocessor option - a filter Normal IIR filter. But what is unusual about him is that he uses a floating point. Not that there was any sense in it, I just read some book about the form of representing numbers, and decided: nonsense this floating point is interesting, let's do it.

image
Fig. 6. Modeling the results of the filter. The logic of the VHDL code is calculated to the bitik accuracy.

There were also plans to turn the project into a system on a chip: adding various blocks written in VHDL to the periphery of the controller. And it seems not so difficult, but the fuse has dried up. Bad thoughts left me, and wander somewhere between programmers and electronics engineers. And now they are called Startups.
So, if someone comes to you and introduces himself as a Startup, think about whether some Durabivator is hiding under him.
And one more PS: On the other hand, while I was working on the Stackcpu project, I learned a good deal of three two programming languages:
1. FORTH, more precisely, a certain subset of it, which is necessary to check the efficiency of the controller.
2. With ++, on pure C it would be hard to write a development environment and a compiler.
3. VHDL, namely the letters of this language is the controller.

It is clear that you can talk for a long time, but this is enough. I will go to deal with other people's ideas, but with my realization!
Actually controller (half megabyte): cloud.mail.ru/public/1cdf4b1d4799/StackCPU.rar

Source: https://habr.com/ru/post/229587/


All Articles