• 0
jrosengarden

8 Bit Adder/Subtractor Design Problem

Question

To All:

I've been having trouble with this 8 bit adder/subtractor.  It's "built up" from a 1 bit full adder, then a 4 bit adder/subtractor and then, finally, into a full 8 bit adder/subtracter.

The 1 bit full adder works perfectly.
The 4 bit adder/subtracter, built up from the 1 bit full adder,  works perfectly.
The final, 8 bit adder/subtractor,  is where my problem lies and I have beat my head against the wall until the dents are now noticeable (in both my head AND the wall).

The 'fix' has GOT to be simple but it sure hasn't popped into my head...and I've tried so many iterations to resolve it I've lost track of what I've done and haven't done! 
I'm pretty certain the problem lies in how the COUT and CIN values are being passed from the 1st 4 bit adder/subtractor iteration to the 2nd...but danged if I can figure out what I've done wrong!

Can ANYBODY tell me what's wrong with the final 8 bit adder/subtractor?  PLEASE (and thank-you!)

addsub_8bit_cascade4.txt

Share this post


Link to post
Share on other sites

17 answers to this question

Recommended Posts

  • 1
Posted (edited)
17 hours ago, D@n said:

Ok, I found the bug in my proof -- I did "read_verilog file.v" instead of "read_verilog -formal file.v"

I've not been too keen to help debug jrosengarden's code for a variety of reasons but this comment from Dan does beg for commentary.

Being overly optimistic or dependent on automated tools is a dangerous way to live. Even if the tools are doing their job correctly there are so many ways to subvert its purpose. There is simply no substitute for using that grey matter that uses so much of the energy that your body produces. Of course training those neural networks to perform well takes time and practice. But it's essential to have the skill to do competent design and verification. Formal verification methods certainly have their place but they are not a substitute for learning how to analyse logic issues.

Even seasoned engineers create code that appears to work on first blush but has hidden issues ready to torpedo your efforts. This is why all HDL code needs a testbench. And, as you get more hours of experience finding corner cases of failure your testbenches will get better at finding them early rather than later.

Many years ago I was implementing an FEC by re-writing Fortran simulation code into DSP assembly code. The customer was willing to pay for verification so all modules had a software 'testbench'. (The software development process and digital logic development process is very similar in many regards). Anyway, part of the Reed-Solomon design appeared to me to need exhaustive testing so instead of relying on finding errors with a simple software testbench I designed a test to run on hardware. The test rig ran for hours without an error and then all a sudden I started getting an error or cluster of errors but at really low rates. It took a few days thinking about the few errors that I found to come up with a plausible explanation which pointed me to a sometimes used bit of Fortran where there was a simple logic error, probably a typo or cut and paste error. The guy who wrote the Fortran algorithms had done proper testing and not found the error. I had done proper testing in software and not found the error but throwing massive amounts of data at the code in hardware did. Finding the error using software would likely have taken days or weeks of computer simulation.

Sometimes you can anticipate the 'usual suspects' and sometimes you can't. Sometimes your automated tools will find issues that they are designed to find and sometimes your problem isn't one of them. And sometimes, even very smart people do dumb things and reach some bad conclusions. The truth is that debugging, whatever it is that you are testing, involves debugging the analysis and thinking of the person running the show. Don't try to take yourself out of the verification process because you are part of the failure both in terms of design and verification.

I should point out that rarely do people write HDL modules that are supposed to do all things for every possible application, at every possible clock rate, etc, etc, etc. We write modules that have limitations and restrictions and are meant to accomplish a limited functionality. This isn't an error. Being unaware of those restrictions, limitations and details that haven't been addressed in the code is an error. Not documenting those restrictions, limitations and details is a very costly error.

Edited by zygot

Share this post


Link to post
Share on other sites
  • 0

@jrosengarden,

I just ran your design through a quick formal analysis.

It works.

Feel free to try out SymbiYosys yourself.  You can read my Verilog tutorial, which includes the basics of how to formally verify a design, on the ZipCPU blog if you'd like.

I'm also attaching the files I used for the proof, so you can take a look at what I verified.

Dan

jrosengarden.tgz

Share this post


Link to post
Share on other sites
  • 0

When I run it thru a simulation OR actually load it onto a Basys3 board...its NOT working.  Not sure how you were able to "prove" that it is working.  I have physical evidence to the contrary.

 

Thanks though!

Share this post


Link to post
Share on other sites
  • 0

I'm designing and simulating/testing with Vivado 2018.3.

The attached files are:

1.  Waveform output:  I have the output starting at a[7:0] input = A0.  You can see the B[7:0] input increasing from 0 to 1 to 2 to 3.....etc.  You can further see the CIN value changing from 0 to 1 for each of the A and B input values.

When CIN = 0 (addition) the result s[7:0] is correct.  For all values of A[7:0] and B[7:0].
When CIN =1 (subtraction) the results are simply dead wrong.

2.  TCL console output:  I have this printed output starting at a[7:0] input = A0 so you can match the various values up to the waveform output.  The columns of data in the TCL output are:
[TIME]  [A Input]. [B Input]. [S output]. [COUT output]. [CIN input].

As you can see...when the circuit is in subtraction mode...something is going awry....and THIS is what I've been trying to resolve.

 

Thanks for your input/guidance!  

TCL_Output.png

Wave_Form_Output.png

Share this post


Link to post
Share on other sites
  • 0

@jrosengarden,

Ok, I found the bug in my proof -- I did "read_verilog file.v" instead of "read_verilog -formal file.v" ... now I'm getting failures on the 4-bit adder.

Tell me, what should the response of the 4-bit adder be if A=0, B=4'hE, and cin=1?  I'm getting an answer of 4'hF with a carry.

Dan

Share this post


Link to post
Share on other sites
  • 0

@jrosengarden,

Can you tell me how the 4-bit subtract is supposed to work?  Specifically, what is the carry supposed to do?  Are you trying to calculate (A-B-carry), or (A-B+carry), or ... I'm not sure.  I'm currently looking at A=8, B=0, and seeing some results I don't get either.

Dan

Share this post


Link to post
Share on other sites
  • 0

Attached is a screen shot showing the waveform output centered at your question;

You'll see that the a[7:0] input value is 0 and the b[7:0] input value is E.  
When CIN = 0 (addition) s7[7:0] = E (0x0 + 0xe = 0xe) --> correct
When CIN =1 (subtraction) s7[7:0] is showing 0x02 when it SHOULD be showing 0xF2

  0000 0000     0x0
- 0000 1110     0xe
==========
  1111 0010     0xf2  (f2 = -14)

Screen Shot 2019-05-03 at 4.35.30 PM.png

Share this post


Link to post
Share on other sites
  • 0

This is a 4 bit ripple add/subtract carry circuit.

CIN = 0 for addition (the B inputs don't get inverted and the CIN value of 0 adds nothing to the circuit's final value) 
CIN = 1 for subtraction ( the B inputs get inverted, 1's complement, and the CIN value of 1 makes it 2's complement)
From there each COUT is then wired up to the CIN of the next 1bit full adder.
 

As I said in my original post...the 4 bit ripple carry adder/subtractor circuit is working fine.  It's when I instantiate 2 of them, in the 8 bit adder/subtractor, that I'm running into my problem.  If I build an 8 bit adder/subtractor out of 8 instantiated 1 bit full adders...that ALSO works fine.

image.thumb.png.7bac90e239dba0e7d238712302b7ed79.png

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

@jrosengarden,

Ok, I think I found your bug.  Your carry bits are messed up.  In the case of the 4-bit, you want to XOR the operation (not cin) with the carry to get the four bit add/subtract to pass.  That will then properly subtract two 4-bit numbers, but it will also leave the carry wrong for the 8-bit adder.  To make the 8-bit add/sub work, you'll need to invert carry[1] at the 8b level as well..

See the attached,

Dan

jrosengarden.tgz

Edited by D@n

Share this post


Link to post
Share on other sites
  • 0

Xor'ing the 2nd instantiation of the 4bit Adder/Subtractor does not resolve the problem.

The 2nd change you suggested is a 'non change'.
assign cout = cin ^ carry[4] is 100% identical to assign cout = op ^ carry[4]

op is assigned the value of CIN at the onset.  Neither op nor CIN are changed so the equations are equivalent.

I'm assuming all the other changes in the code are necessary for you to run it thru your SymbiYosys software and are not pertinent to the actual circuit...so I did not add them in.

 

Thanks anyhow...appreciate the effort!

Share this post


Link to post
Share on other sites
  • 0

You missed a change.  Check out the line:

addsub_4bit nibble1(carry[2], s[7:4], a[7:4], b[7:4], carry[1]^op, op);

Dan

Share this post


Link to post
Share on other sites
  • 0

yes, that is the change I was referring to; xor'ing the 2nd instantiation of the 4 bit adder/subtractor.

However, to be sure I wasn't missing ANY of your changes I pasted your entire version into the design.  Once I realized you had "IfDef"s surrounding your necessary changes I realized they'd do no harm in the Verilog design.  However I DID have to comment out this line;  `default_nettype none

So I ran it again and perused the wave form panel in detail.  Strangely enough the design works all the way thru a[7:0]=0xB) and b[7:0] = 0x0.
Beyond that point...the addition's are correct but the subtractions are incorrect.

CLOSE...but no cigar.  

This has been what I've been doing for the past 2 days...trying zillion's of 'ideas'/iterations to resolve the issue but I just can't seem to find one.
Your solution definitely is the closest the design has come to fully working.

See the attached Waveform to see the 'breakdown' point.

 

Screen Shot 2019-05-03 at 5.29.28 PM.png

Share this post


Link to post
Share on other sites
  • 0

actually - the closer I examine the waveform panel there are problems manifesting themselves even before A=0xB0 and B=0x00.  

It's definitely still not right and the 2 changes you've suggested don't fix the problem.  Take a look at the attached waveform.  I have it starting at 89,919,000 ns.  If you follow along with the A, B and CIN inputs...you'll see problems even here....WAY before the problems I identified at A=0xB0 and B=0x00

Still scratching my head!

Screen Shot 2019-05-03 at 5.46.01 PM.png

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now