I am looking for some way using discrete logic (TTL) to decrement an 8-bit value by one.

Basically I want to present it with an 8 bit bus with a binary number on it, and have it give an output of the input minus one on its output:


...I3 I2 I1 I0 | ...Q3 Q2 Q1 Q0
   0  0  0  0  |    1  1  1  1
   0  0  0  1  |    0  0  0  0
   0  0  1  0  |    0  0  0  1
   0  0  1  1  |    0  0  1  0
   1  1  1  1  |    1  1  1  0

I have been googling and drawn a blank for a chip that can do it, and I have been racking my brains of the best way to do it using just normal gates.

Does anyone either know of a chip for this, or have some ideas on how I could construct it from discrete gates?

  • \$\begingroup\$ based on some comments you left, it sounds like your real problem is that you are trying to address one of 256 modules. if that's the case, the usual way to approach this is to just pass the same 8 bits to all the modules, and each module then decodes one unique address. \$\endgroup\$ – JustJeff Jun 24 '11 at 21:34
  • \$\begingroup\$ That's not how I want it to work though - that relies on giving each module a unique address. I want to address them by their position in the bus. \$\endgroup\$ – Majenko Jun 24 '11 at 22:09
  • \$\begingroup\$ all righty then, that's an interesting requirement, and does knock out the address decoder approach. \$\endgroup\$ – JustJeff Jun 24 '11 at 23:53

Have you considered adders? You can subtract with an adder.

You just need to add -1 to the input value. A pair of 7483 4-bit full adders should handle your 8-bit input. Apply the input X to the 'A' inputs, and apply the binary representation of -1 to the 'B' inputs. Fortunately, the 2's complement representation of -1 is all ones; this means that if you just tie the 'B' inputs all high, you're done. What comes out should be X-1.

  • \$\begingroup\$ actually it's the 7483A .. \$\endgroup\$ – JustJeff Jun 24 '11 at 1:38
  • \$\begingroup\$ Ah - adders, yes. I will see if I can get hold of some and give it a try. \$\endgroup\$ – Majenko Jun 24 '11 at 7:56
  • \$\begingroup\$ Ordered. One quickie - linking them together to form 8 bits - is it as simple as linking carry out on the LSN to carry in on the MSN? \$\endgroup\$ – Majenko Jun 24 '11 at 8:22
  • \$\begingroup\$ @Matt Jenkins - Yes \$\endgroup\$ – stevenvh Jun 24 '11 at 9:07
  • \$\begingroup\$ @Matt Jenkins - note that the carry-in on the LSN has to be wired the right way. I want to say it needs to be pulled low, but not 100% sure about that. When in doubt, consult the datasheet. \$\endgroup\$ – JustJeff Jun 24 '11 at 23:55

It's not impossible to do this using discrete gates, but it isn't trivial either. You can always cheat and extend on the schematic of the 74HC83 :-)

enter image description here

One other solution is to use a CPLD. You'll need to know some HDL (Hardware Description Language), like VHDL. In VHDL decrementing is just something like

output = input - 1

and if you want to you can define input and output as 32-bit values, or even 128-bit. The VHDL synthesizer will translate this into the correct logic.

Another way to do this is using a parallel lookup EEPROM (or EPROM, whatever). You only need a 256 bytes part, so just any existing device will do. Fill the 256 bytes with a table of 8-bit values, starting with -1 (0b11111111), then 0, 1, and so on. If you supply an 8-bit value to the address inputs you get that value - 1 on the data outputs.

  • \$\begingroup\$ Alas CPLDs are out of the question unless I could find a 100mil DIP version of one... The EEPROM idea is a good one though - may be doable if the adders don't come through for me. \$\endgroup\$ – Majenko Jun 24 '11 at 8:21
  • \$\begingroup\$ Why you need DIP? Soldering soic & QFP chips is not hard... Also there are prototyping PCB's for them... I highly recommend you to go this way :-D \$\endgroup\$ – BarsMonster Jun 24 '11 at 9:22
  • 1
    \$\begingroup\$ The EEPROM idea is seriously brilliant. \$\endgroup\$ – Rick_2047 Jun 24 '11 at 12:47
  • \$\begingroup\$ @Rick - thanks. The nice thing about it is that you can use it to do all kinds of logical transformations, like BCD to binary and vice versa. Just compile the appropriate lookup table. \$\endgroup\$ – stevenvh Jun 24 '11 at 17:10
  • \$\begingroup\$ @stevenvh hats off, something very simple but really handy \$\endgroup\$ – Rick_2047 Jun 24 '11 at 17:48

Will 255 IDs do? You could implement a 255 step sequence like a linear feedback shift register using only wiring and an XOR IC such as 7486.

Consider your 8-wire bus to be the current state of the LFSR. Shift each individual wire over one step and produce the new bit using the XOR or XNOR gates to produce the output bus for your next module. Each module then has a different number in the sequence.


Taps:   * *
ID1:  0 0 1
       \ \   0^1=1
ID2:  1 0 0
       \ \   0^0=0
ID3:  0 1 0
       \ \   1^0=1
ID4:  1 0 1
       \ \   0^1=1
ID5:  1 1 0
       \ \   1^0=1
ID6:  1 1 1
       \ \   1^1=0
ID7:  0 1 1

The backslashes represent simple wires, and each ID is generated by a new module.

A completely different approach is to equip every module with a simple up counter and a single 1-bit register. Wire the register's output to both the enable for the counter and the next module's register input. The clock will be common to registers and counters. Then clear all registers and counters, and start clocking in the opposite state through the registers; as each register switches, the counters will stop (or start), giving a unique address to each module. This only requires three wires and as many clock ticks as modules.

I don't know if either of these fits your problem; what are you using these IDs for?

  • \$\begingroup\$ @Yann - could you elaborate on that? I don't think I know what you're talking about. (Yes, I do know what LFSRs are) \$\endgroup\$ – stevenvh Jun 28 '11 at 18:07
  • \$\begingroup\$ Does this expansion help? I feel like I'm missing a bit of the puzzle. \$\endgroup\$ – Yann Vernier Jun 28 '11 at 18:32
  • \$\begingroup\$ @Yann - Hm, still don't understand what you mean. Sure this isn't an answer to a different question? (Register solutions are out, anyway) \$\endgroup\$ – stevenvh Jun 28 '11 at 18:33
  • \$\begingroup\$ As I'm reading the question, you have an address bus going into each module, and want it passed through with a combinational change to the next module, such that the address observed will be a match only for one module. My first followup question is if the sequence step needs to be A-1; using a sequence like (a0^a1)|(a<<1) takes less logic, so less delay and complexity to build. The other variant, clocked address generation, would be a one-time operation; I'm not clear on why clocked solutions are out, and in particular, the combinational delay may be considerable with such a long chain. \$\endgroup\$ – Yann Vernier Jun 28 '11 at 18:37
  • \$\begingroup\$ The sequence would be thus: 1) master signals address X. 2) Each module takes the signaled address and checks to see if it's 0. Passes on the address-1 to the next module. 3) Module where address is 0 switches to SPI slave mode. Signals master it's ready. 4) Master sends / receives data. 5) Module is released to go back to SPI master mode. Modules need to be completely config free as far as addressing goes, so no address matching. Also the address to match must be the same for each module. \$\endgroup\$ – Majenko Jun 28 '11 at 20:54

You could maybe chain two 74LS191 or '193 together. Use the "down counter" clock input.

Or a single 74LS469 will do what you want, if you can find one.

  • \$\begingroup\$ Unfortunately I can't use a clock signal for this - there can be no (or only tiny) propagation delays in the chain. \$\endgroup\$ – Majenko Jun 24 '11 at 7:55
  • \$\begingroup\$ @Matt Jenkins If the propagation delays are so critical, how you plan to keep all devices synchronized without a clock? Propagation delay can differ among devices from different batches for example. \$\endgroup\$ – AndrejaKo Jun 24 '11 at 8:14
  • \$\begingroup\$ I don't. This is for selecting 1 of (up to) 256 individual modules. The modules themselves are internally clocked. Once the module is selected a clock will be provided for data transfer. Each module looks to see if the incoming address is 0 - if it is then this module is the one selected. It passes the address-1 to the next module in the chain which does the same. \$\endgroup\$ – Majenko Jun 24 '11 at 8:18
  • 1
    \$\begingroup\$ @Matt Jenkins - then you may actually want to use a counter. Thing is, when you change the input, differences in propagation through a combinatorial circuit like this could lead to transient outputs that don't fit the decrement sequence. When you change the input, the output will quickly settle to the correct value, but there may be observable glitches. For that matter, do all your input bits change simultaneously? Perhaps not. For this reason it might be best if you did use a clock to latch the outputs once they're stable. And if you're clocking anyway, why not a counter like Mark said? \$\endgroup\$ – JustJeff Jun 24 '11 at 9:41
  • \$\begingroup\$ @Matt Jenkins - it occurs to me, since you intend on including the decrementer in each of the modules, that to use a counter, you'd have to generate a load pulse followed by a clock to do the down-count.. and how would you know when to make those? OK, an actual counter may be out, but you'd still probably want to run the output of the decrement circuit through an edge-triggered register (e.g. 74374) before passing it along. Clock all the registers w/the same clock, pass the clock along with the number. Set frequency to give margin over max propagation delay through your decrementer. \$\endgroup\$ – JustJeff Jun 24 '11 at 9:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.