flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
As a rare breed of software engineering who has mostly done hardware design, thanks mostly to discovering assembly, here goes:
For [digital] hardware design, most development occurs in a hardware description language (HDL) - usually Verilog, sometimes VHDL. There are several levels: physical implementation, which concerns silicon area and power and clock/timing; bring-up/prototyping, which is either a test board or FPGA; simulation/modelling, which can be anything from gate level to high level C++/MATLAB; and design itself. Some designs may also have some analogue stages for "external" IO/signals (clocks, wires, WiFi etc) but I'm less familiar with this. HDL is a slight blend of C and Pascal in terms of syntax but importantly everything is parallel (as if it was automatically multi-threaded) event/signal driven and can have varied timing. Variables, from a software view, are physical signal lines (e.g. 8bit int is 8 wires); assignments may be either combinatorial (a chain of gates that have no clock driving them but cannot "store" a value) or pipelined/registered (chains of gates with one or more clocked registers to hold values) - these are also needed to prevent timing violations where a combinatorial path takes too long for the physical signal form the inputs to change the outputs in time; finally execution is determined by one or more signals - these can be thought of as interrupt service routines but for every single stage of the design. Debugging usually involves looking at wave files of all of the signals from a simulation and/or trace files that track certain points in the design for easier viewing/processing. Later on, this may also be more accurately debugged on an FPGA or emulator but these are respectively much slower. Instruction set design is usually a fight between software developers and hardware designers and the architects/customers. Software generally propose "would-like" optimisations and hardware designers determine how feasible or how much power/area/real time is needed. If this is acceptable to to the customer it is implemented otherwise modified/reduced or rejected (normally this is where software workarounds happen). This is how many exploits occur when the consideration of security is lesser than the target on performance or a new addition is made without full consideration of the rest of the existing system. |
|||
![]() |
|
cod3b453 wrote: Variables, from a software view, are physical signal lines (e.g. 8bit int is 8 wires); assignments may be either combinatorial (a chain of gates that have no clock driving them but cannot "store" a value) or pipelined/registered (chains of gates with one or more clocked registers to hold values) - these are also needed to prevent timing violations where a combinatorial path takes too long for the physical signal form the inputs to change the outputs in time; finally execution is determined by one or more signals - these can be thought of as interrupt service routines but for every single stage of the design. The first part about variables, does that mean constants? (since they cannot "store" a value). And what is about timing violations on the second class of variables? |
|||
![]() |
|
Furs wrote:
From my small experience with VHDL, you should forget about variables. Every value is basically a signal on a wire. Variables (like something that can hold a value) are also supported but in fact you’re describing the structure of a hardware unit. Treating signals as variables leads to all kinds of problems from ambiguous descriptions (remember, HDL stands for Hardware Description Language, it’s not a programming language!) to creating unnecessary latches and other stateful stuff which in turn might cause unwanted behaviour and increasing complexity of the hardware unit. When you write something like Code: a <= b xor c |
|||
![]() |
|
Thanks. That makes sense. But how do you do stuff that needs more than 1 clock cycle and thus "executes" in states? Wouldn't it have to remember? I suppose internal registers are a thing
![]() So basically there's no "control flow" (if and loops) in HDL and you have to implement it with some sort of state machine but idk how the clock cycles work. Of course I know that the underlying hardware doesn't support "execution" like this, I just (erroneously) assumed that the language is high-level and converted by a compiler from normal execution flow to some hardware states, heh. I guess compilers aren't at that level yet. |
|||
![]() |
|
cod3b453 wrote: Instruction set design is usually a fight between software developers and hardware designers and the architects/customers. Software generally propose "would-like" optimisations and hardware designers determine how feasible or how much power/area/real time is needed. If this is acceptable to to the customer it is implemented otherwise modified/reduced or rejected (normally this is where software workarounds happen). This is how many exploits occur when the consideration of security is lesser than the target on performance or a new addition is made without full consideration of the rest of the existing system. Furs, if you would like to learn about hardware designs for CPU type circuits, then there are some simple cut down version available for download; a basic 4-bit CPU might be a good place to start. There are even public core IPs available for things like the 8048 and 6502. |
|||
![]() |
|
Thanks, I'm not really interested (at this point?) in actually designing hardware, just some basic concepts, like how it works on a largish scale. I know clock cycles are used for synchronization, but is HDL just a giant state machine with states being internal registers? (and obviously, other memory like caches and main memory). Still, any links would be welcome.
![]() |
|||
![]() |
|
HDL is a language but what is designed with it is, yes, basically a state machine.
Quote: But how do you do stuff that needs more than 1 clock cycle and thus "executes" in states? Wouldn't it have to remember? I suppose internal registers are a thing Code: process (EN, D) begin if (EN = '1') then Q <= D; end if; end process; * Whenever EN becomes 1 the signal (wire) Q gets the value of signal (wire) D. * In all other cases no changes are made to the Q signal, so it basically holds the value it was assigned before. A rule of thumb applicable to this particular case is that if you don’t want stateful stuff, you should be careful to have all possible cases covered. I’ll try another example: Code: process (EN, D) begin if (EN = '1') then Q <= D; else Q <= not D; end if; end process; |
|||
![]() |
|
I wasn't aware that an "if" construct existed, this makes it much easier. Also, I find it somewhat "natural" to think in wires/connections like that, due to some modular designs in some DSP software I'm familiar with, so now it makes a lot of sense, thanks. (in terms of assembly, I'd say it's like the cmov instruction, of course operating on individual bits (wires) instead)
BTW wires in CPUs/digital hardware can only contain the values 0 and 1 right? So basically they're bits? Just to be sure. |
|||
![]() |
|
Furs wrote: BTW wires in CPUs/digital hardware can only contain the values 0 and 1 right? So basically they're bits? Just to be sure. That’s where my experience ends. I only wrote a few descriptions and used some libraries that let me think only 0 and 1 are possible. But, AFAIK, nearly 9 possible values are actually supported although not all of them can be relied on, I guess. |
|||
![]() |
|
0, 1, Hi-Z, pulled-low, pulled-high, input/output, etc. There are many states a signal can be in.
|
|||
![]() |
|
[quote="Furs"BTW wires in CPUs/digital hardware can only contain the values 0 and 1 right?[/quote] wires can hold multiples signals, 1 & 0 it is only most used case."+","-","no signal" - and you got trit.
_________________ I don`t like to refer by "you" to one person. My soul requires acronim "thou" instead. |
|||
![]() |
|
Furs wrote: Can you elaborate on this please? Constants usually exist as ROMs, where the values are directly attached to 0 or 1 (and can easily be modified between production runs) or implicitly through the physical wires e.g. the number 5 would be attaching positive to bits 2 and 0 and negative to the rest (or even not having them at all if they have no actual side-effect). "Variables" [signals] are transmitted through some combination of gates (not/[n]or/[n]and/x[n]or or add/sub/shift/mul/div/mod etc) from a source register to a destination register. These gates have a delay associated with them that will also vary according to the logic table e.g. A or (large expression B=b0 and ... and bN) can propagate 1 faster when A is true compared to the longer delay of B. Note that these gates have no clock and so can take as long as they want but for the system to work reliably we have to have the answer within one clock [duty] cycle since this is both how long the source input is available for and how much time it has to propagate the result to the destination before it latches whatever value it has received*. If this is not guaranteed [for all permutations] it is a timing violation. This is normally resolved by introducing additional intermediate register stages ("pipelining") within the full logic tree to break down each sub-stage to a faster delay that meets timing at the expense of all cases have a fixed additional delay. Alternatively, changes to the clock frequency or expression can sometimes be made to avoid this - the balance is determined by the physical implementation and its operating parameters, see below. *Different HDL languages define difference cases and these cases are based on a physical library provided by the fab describing the behaviour of the semiconductor (e.g. silicon), any "pre-made" component patterns (RAM cells, registers, ROMs) and their optimal layout when doing placement. In the ideal case, we only have 0 or 1 but in reality there are infinite levels between them when switching between them due to the "small" delay based on voltage and nearby circuitry (capacitance/resistance). If we assume 0 is 0 Volt and 1 is 1 Volt: gates can have a variety of characteristics that mean between say 0V and 0.3V it is a 0 and between 0.5V and 1V it is a 1 but the remaining region could be one or more defined states. Depending on the HDL and what the signal is, these usually include an 'X' (unknown/any and driven) state and a 'Z' (high impedance and non-driven) state but also varying levels of "probably 0/1", "maybe 0/1", "conditionally 0/1", which in most cases should all be avoided like the plague. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2019, Tomasz Grysztar.
Powered by rwasa.