zygot

Members
  • Content count

    331
  • Joined

  • Last visited

  • Days Won

    13

zygot last won the day on August 22

zygot had the most liked content!

About zygot

  • Rank
    Prolific Poster

Recent Profile Visitors

2,186 profile views
  1. FPGA based PWM generation

    @Piasa, In implementation the idea works fairly well regardless of how the input data is encoded. This is not, in my experience, how things work in FPGA development but your algorithm is a special case. As a consequence you can get the same reconstructed waveform shape with a high pulse density or a low pulse density. I assume that the AC coupling helps with that. An unfortunate "feature" of this PDM encoding is that the msb's of the word being compared to the bit-reversed counter are really important. As the counter period is not related or synchronized to the sample period the effect of the bit-reversed counter low bits changing from sample period to sample period have a greater prominence in the pulse density and reconstructed output. This is why scaling the input to achieve a tolerable sound level has such a negative effect on the reconstructed signal. At least that's how I understand it. Of course there's more going on because the modulator in the SSM2377 is converting the reconstructed input, which is not necessarily within the common-mode input specification and creating a different PDM to drive the speaker. Another unfortunate "feature" is that higher input data sample rates relative to a given clock rate have a greater loss in precision. Usually, we want higher sampling rates to improve fidelity. Lastly, the PDM accuracy doesn't scale well with increasing input data width as it would using traditional A/D converters.
  2. FPGA based PWM generation

    @D@n, Actually the ramp works out fine. The differences are subtle. In the middle picture where my code is driving the amplifier and not flipping bits the PDM has the fewest pulses at the reconstructed ramp minimum whereas your code has the fewest pulses in the middle of the ramp. Sine wave msb issues are more dramatic for sure. The point of the pictures is this. My the waveform was encoded using unsigned 16-bit data. My VHDL code doesn't know about the existence of signed values and your code thinks that it's converting two's compliment values into unsigned values. And yet the result, for the same data samples, is similar, regardless of the msb ( except for phase ). Except for levels that produce phase reversals all the the sine waves look pretty much the same as well. The annotated snippet is provided to encourage those who want to understand what's happening where to look. And it's all about that bit-reversed counter.. which is analogous to electrical commutation.. and that simple 4-bit table showing two's compliment and offset binary encoding. I could show pictures of sine waves with phase reversals (inversions) but I don't think that this would resolve anything that we've discussed. I could also show a 5512.5 Hz tone that has been scaled by 1/16 to make the resulting sound level reasonably tolerable ( now we've lost the bottom 5 bits as well as the top 4 and are left have 8 7-bit samples ) and show a pretty distorted and noisy sine wave but that's up to anyone with the interest to do for themselves. While I am sure that both you and Piasa are wrong about what is happening with this algorithm I don't feel a need to convince either of you. If anyone is interested in working this out for themselves, the project files at here. Those with an inquisitive mind will find a lot to play with. Those who prefer assumptions over experimentation aren't my audience. I might be wrong about this ( I've been wrong about other things related to this thread...) but I don't think that there are many people following this thread. PS. I'll need some encouragement to post more on this topic. Otherwise that PmodAMP2 is going into the a drawer to spend the rest of it's life ( unless I can think of a non-audio application.... hmmmm)
  3. FPGA based PWM generation

    In the current version of my project I've instrumented the design and allow the VHDL simulation to print out signal states. testsnippet.txt is an annotated snippet from the testbench output file RIGOL Print Screen9-28-2017 11_27_18 AM.614.png is a scope shot of a 16 level ramp waveform produced by TestIP.py ( all unsigned values ) with msb flipping R0=0x09 RIGOL Print Screen9-28-2017 11_31_20 AM.215.png is a scope shot of the same waveform without flipping the msb. R0=0x29 RIGOL Print Screen9-28-2017 12_18_24 PM.996.png has Dan's code with the same waveform driving JA pin 1 instead of my code driving it. R0=0x49 For all screen shots R5 is 0xFFFF. Thu Sep 28 112345 2017.txt is the log file of the 16 level waveform produced by the python test script. In the scope pictures channel 3 in purple is the reconstructed PDM at C3 on the side connected to the SSM2237 +Vin pin. Channel 1 is JA pin 1 and Channel 2 is JA pin 3 which is my pwm output and Dan's respectively. At this point I'm bored with silly arguments so unless anyone who has taken the time to actually experiment with this asks any "interesting" questions I'm on to more useful things. Thu Sep 28 112345 2017.txt testsnippet.txt
  4. FPGA based PWM generation

    Perhaps you'd like to provide your spice models that allowed you to verify all of this. I didn't use spice but I do have a reasonably good scope, which I've been using with my little project source to get a reasonably accurate sense of all of those things. As to not being interested in what an actual implementation in hardware is doing to a theoretical concept I really don't understand that at all.
  5. FPGA based PWM generation

    Ah, now we're getting somewhere. The notion of infinite precision numbers is not one that can be expressed in FPGA logic. In logic expressed as gates you cannot take a slice of the low 4 bits of an 8-bit signed signal ( you call it truncation ) and call it an unsigned 4-bit value without changing the meaning of the bits in the new signal. And, we can treat any bit in any signal in any manner we want to in an HDL. What we can't do is change the original encoding. When you decide to "truncate and treat the msb as a sign ( polarity ) bit that's what you are doing. It works for this code because of the cyclic nature of the bit-reversed counter being compared to an input ( that is unsigned, two's compliment, offset binary msb flipped or msb not flipped). This is an important concept because it has to do with HDL and FPGA interpretations. Let me offer an example. signal a : std_logic_vector(3 downto 0) := "000" process(sysclk) begin if (rising_edge(sysclk)) then a <= a+1; end if; end process; One might interpret the process above an adder. I don't know of any synthesis tool that doesn't express this as: a=(a+1) mod 16. This is not truncation but wrapping from 15 to 0. This is expressed as counter logic. On the other hand signal a : std_logic_vector(3 downto 0); signal b : std_logic_vector(3 downto 0); signal c : std_logic_vector(3 downto 0); process(sysclk) begin if (rising_edge(sysclk)) then c <= a+b; end if; end process; In an HDL you will get a synthesis error because the sum of two 4-bit signals requires a 5-bit signal. 14 ("1110") + 14 ("1110") = "11100". So if you are clever you can take advantage of HDL rules and the properties of number representations but you had better know what you are doing. A concept that works in a strictly mathematical world has to take into account the reality of digital logic, HDL syntax and synthesis interpretation of HDL statements. Not only does your "better pwm" lose 5 bits of full scale precision at 44.1KHz sampling rate with a 100 MHz clock but a 48KHz or 96KHz or 128KHz sampling rate with the same clock rate it loses even more bits. As to whether or not your PDM is better than a PWM I really don't care as neither is particularly a high quality audio approach. I do care about whether the resulting audio is hurting my hearing which is why I have a scaler to set some sort of sound level. Any audio application requires controlling sound level as well as fidelity in replicating the sample inputs. I'm assuming that neither you nor Piasa has bothered to play around with the project that I uploaded. You might find it interesting. I run your code along side my code that can have the msb flipped or not. Try it and see what happens. If there's an interest I may upload a newer version that has some instrumentation and allows for changing the sample rate. If you can find a way to implement a very complicated concept in a very elegant and extremely simple way that doesn't come with negative consequences then you can put the following sign on your office door: "Do not disturb. Genius at Work". For the rest of us consigned to cubicles in a large room we will have to find those negative consequences for our clever solutions My real complaint of course is not with the general idea of driving an amplifier with a digital signal instead of using an A/D converter. This is interesting if not particularly useful. My complaint is making claims without proper explanation, offering plots that aren't reproducible and obviously not real, and creating confusion in your intended audience.
  6. FPGA based PWM generation

    @Piasa, Let's create a signal: S=[-8,-3,2,7] In 4-bit two's compliment binary this is: ST=[1000,1101,0010,0111] In 4-bit offset binary this is: SO=[0000,0101,1010,1111] If we change the msb in either binary format from 0 to 1 this has the effect of subtracting 8 (2^3). If we change the msb from 1 to 0 this has the effect of adding 8. Large negative values become small positive values and visa versa. FST=[0000,0101,1010,1111] = [0,5,-6,-1] FSO=[1000,1101,0010,0111] = [0,5,-6,-1] We can't represent S in unsigned binary format unless we halve the magnitude and offset it by 8. If we have a 4-bit unsigned counter clocked at 100 MHz the bit0 toggles at 50 MHz, bit1 toggles at 25 MHz and so on. The bit-reversed version of this counter has bit3 toggling at 50 MHz, bit2 toggling at 25 MHz and so on. The counter monotonically increases until it wraps from 15 to 0. The bit-reversed counter is: [0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15] which is now cyclic with varying magnitude. If we compare the bit-reversed counter to any of the 16 possible input values, regardless of how the data was encoded we can get a pulse density representation because of this cyclic nature as long as the input data changes once per counter period. For D@n's code, the input data sample period of 44.1 KHz with a 100 MHz clock is about 1/30th the counter period. This means that the encoding into pulse density loses about 5 bits of precision. If we want to use this IP as an audio application we need to scale the data to achieve reasonable sound levels whether the amplifier gain is set to 6 dB or 12 dB. I encourage anyone interested to experiment with the test project that I uploaded earlier.
  7. FPGA based PWM generation

    Oh I forgot that I wanted to mention to the casual observers that if nothing else the project source shows how to create waveforms in Python, upload them into an FPGA block ram memory and have a waveform generator that runs at a particular sample rate. Python lists are not ideal containers for arrays of things but it does work on Windows and Linux and supports the serial port nicely. If I were using the DPTI interface I'd use C and be a happier camper ( there are a few things about Python that I don't like but it doesn't stop me from using it extensively ). Even if you don't care about PWMs, PDM, the PmodAMP2 or binary numbers there might be something worth slogging through all the excess verbage that Piasa finds irritating. Oh, and don't forget about simulation and verification...
  8. FPGA based PWM generation

    @D@n As to a PWM , as long as the counter over-flow interval is the same as the input data sample period I agree with your logic. You could also use an up-down counter and center your PWM around the mid-point of the sample period. Yes, I do remember that criticism. It turns out that I hadn't properly understood the reconstruction filter characteristics. I had always expected that there would be some sort of analog representation of a waveform... just not nearly as good as it is. The SSM2237 still needs an analog input ( preferably driven differentially ). It also expects the analog common-mode input to be between 1V and Vdd-1 V ( for the PmodAMP2 this is 1V-2.3V ). The Sigma-Delta modulator in the SSM2237 is clocked at about 6 MHz which probably helps smooth the input. As to how well this all works you can download the last version IPTEST_R2 and see for yourself. Assessing the reconstructed analog input to the SSM2237 will be hard to do without a good scope. I may try using some well known PC audio tools to see if it's reasonable to make an assessment of the amplifier output. I suggest that you try really low tones < 200 Hz and really high tones above 5 KHz to see it in action. Really low tones should be quite accurate as there are a lot of samples per sample period. Lastly, you should change the sample scale factor to see low signal levels being reconstructed. One way to look at the application is to think of a waveform putting energy into a an RC load and removing it proportionally to the duty cycle of the digital waveform. A 50% duty waveform should have no net exchange of energy. It's a bit more complex than that and as you saw in your reference above the time constant for putting energy into and out of a reactive load is not symmetric. But, counter to my instincts it all works better than I thought it would. That's due to the design of the reconstruction filter. It's important to understand that the analog inputs on SSM2237 on the PmodAMP2 are AC-coupled. The only argument that I see us as having is about binary representation of values. As I understand it the method that maps input values to pulse density waveforms effectively removes the sign bit. I still have some playing around to do on that regard. I have not yet made a plan for analyzing the SSM2237 output quality.
  9. FPGA based PWM generation

    It should be noted for anyone wanting to replicate this algorithm as a general purpose application that the FPGA IO are not designed to drive highly reactive loads. The 200 ohm series resistor on the Nexys Video JA pins and the first 300 ohm resistor on the PmodAMP2 limit the current into and out of the IO pin. Still there is a considerable amount of capacitive loading. When using IO, and especially when using IO with a non-standard load, you should do the analysis of power dissipation and voltages as seen by the IO pin. I you are replicating the project on hardware you should be aware that my version of the IP uses only unsigned values and the msb should not be flipping. It does so as a default only to replicate D@n's code behaviour.
  10. FPGA based PWM generation

    @Piasa Yes I can. My testbed had a logic error that stalled the waveform generation under certain conditions. Here is a better version of the project. It now includes the correct testbench and the control program has minor cosmetic improvements. The general algorithm works with signed or unsigned inputs as you indicate. On the PmodAMP2 there is considerable distortion with tones above 5 KHz but this is not unexpected as the number of samples are low and the load impedance is fixed. For low tones under 1 KHz the results are pretty reasonable (though not particularly for an audiophile's tastes). IPTEST_R2.zip
  11. FPGA based PWM generation

    @Piasa, Back to this comment I don't believe that testing of the algorithm on hardware quite agrees with the above description. The description might be correct but I don't believe that the implementation does exactly what it should be doing to agree with the description. Of course I've been wrong about other aspect of this topic. Here is my test project. I do hope that anyone interested in this conversation will look it over and try it in simulation and on hardware if they can. IPTEST_R1.zip
  12. FPGA based PWM generation

    @D@n Yesterday I received a PmodAMP2 so I was able to try out my testbed using the Nexys Video. The project HDL runs fine but the support code needs work to be in a finished state. I will post when ready. I mention this now because I as able to reach some conclusions that should be posted in the interim. All of these involve aspects of your "better PWM" that really bothered me which turned out not to be issues. My testbed runs your wbpwmaudio as well as my version at 100 MHz so there are 10 ns pulses driving the analog input pin of the PmodAMP2. The following points are counter to what I expected ( that is to say my expectations were incorrect ). The signal quality of the 100 MHz PDM is quite adequate at the input to the initial low pass filter. The PDM does get converted into a reasonable representation of the source digital waveform at the SSM2237 input. The wbpwmaudio counter interval is independent of the sampling period ( as long as it's longer ). I think that I've figured out how the pulse density encoding works. I will put the project code and observations here for anyone who wants to work this out when ready. I'm still working through a few details about how it all works.
  13. FPGA based PWM generation

    @Piasa Ah, even more illuminating. Thank you.
  14. FPGA based PWM generation

    Yeah, It makes sense to me because I am implementing a testbed in HDL to test the actual hardware. I want to use an algorithm that works with any input value. When you flip the sign bit of a signed binary number you change how the data bits are to be interpreted. If you don't care about the value of the remaining bit then why not just ignore the sign bit in the comparison logic? The HDL compares a 16 bit binary word without a sign bit to one with a sign bit and this cannot be correct. As I've pointed out if you don't use signed data then this whole issue becomes moot. Pardon my reluctance to buy into your argument the implementation is irrelevant to the discussion as this is exactly the kind of detail that I've seen break a design implementation. I will be uploading my testbed with a simulation testbench. You might find it interesting. I don't disagree that evaluating the IP as an independent entity is worthwhile. As to whether or not the output of D@n's PDM turns into the expected analog signal that the SSM2237 is designed to use, that's not be shown by anyone yet. This includes D@n's recently released test report. This is certainly illuminating but doesn't answer the question as to what is going on to get that "more pleasing" sound that he hears from his PmodAMP2 connected speaker. I am also not understanding how comparing a permutation of an up counter to an input encodes a representation of the input. I understand how a pwm does that. I understand how it provides many more transitions. Perhaps you might offer your insight as to how this works? Your argument: "In this application, the 16b signed value is re-encoded into a representation that will be used with unsigned inequality comparison. The value that is represented by the conversion is a signed value -- we are mapping some code words to negative values. However, the representation is used with unsigned operators. From an implementation perspective it is unsigned. Most languages force an interpretation of either signed/unsigned even when neither are correct." is a helpful insight that I've been missing though not complete to grasping the encoding of amplitude. I do want to say that if someone wants to know, say, how to use a feature of Vivado, then the answer(s) should be as concise as can be clearly presented. When a discussion is complicated and the goal is learning then I say let the discussion go where it needs to go as new questions arise. The reader is free to speed-read through what isn't interesting, focus on what is or just ignore the whole thread all together if there is no value to it. Learning is a equal opportunity pursuit and the process works differently for everyone.
  15. FPGA based PWM generation

    @D@n I glanced at the referenced test directory material. It seems to reinforce my suspicion that you've never done an HDL simulation and that all of your design/verification flow is in C++. One aspect of ModelSim or Vivado simulator is that the simulator understands HDL and the details of the language on the most basic level. Working in C++ allows one to abstract away a lot of those details which can be very helpful but also an impediment. I suggest you should develop a facility with the HDL testbench writing and simulation flow.