hamster

Members
  • Content Count

    477
  • Joined

  • Last visited

  • Days Won

    75

Everything posted by hamster

  1. I don't think you have to keep it consistent within a module. but it makes sense to. Conventions I have seen and use are: signals are always "downto". This makes numbers make sense - e.g. "00110000"; sig_downto <= "00110000"; assigns binary 48 sig_to <= "00110000"; assigns binary 12; Arrays are always "to". This makes initialization make sense.- the first element in the list goes into slot zero. If you do want to flip bits, this can do it for you: out_sig(0) <= in_sig(2) when rev = '1' else in_sig(0); out_sig(1) <= in_sig(1) when rev = '1' else in_sig(1); out_sig(2) <= in_sig(0) when rev = '1' else in_sig(2);
  2. I can't see what the issue is... can you describe exactly how are you expecting this to reverse the order of the bits? If your assignment into 'reverse_order_bits' does change the order, then when you assign that into 'out_sig' then that will also reverse the order. So if the output is always the input, then 'rev' (and that means 'SW[4]') also has no effect, and can be optimized out. And if the out_sig always equals in_sig, then your design does indeed contains no logic, just three connections from input pins to output pins. All seems consistent to me. Try it with explicitly reversing the order of the bits.
  3. Hi, The common way would be to use slices of the std_logic_vector: signal seg : std_logic_vector(3 downto 0) := "0001"; ... if rising_edge(clk_240) then seg <= seg(2 downto 0) & seg(3); end if or the opposite way: if rising_edge(clk_240) then seg <= seg(0) & seg(3 downto 1); end if You most likely also want a concurrent statement to assign the value to the module's output, and allow for the fact that the display are usually active low (ii.e. digits are switched on when the output is 0). seg_output <= not seg; This also helps, because if 'seg'_output is declared as being "out" in the module definition you can't read it's value to update it (yes, a little bit silly for VHDL). VHDL does have ROL, ROR, SLA and SRL operators, but nobody uses them as far as I know.
  4. I believe you can set a simulation flag to enforce range bounds checking, and it will error if you end up with an out-of-range value. It is off by default. You got it lucky with your range testing on hardware - if you had a a range from 0 to 5, it would most likely still count through 6 and 7. The synthesis tools has this sort of internal dialog: - Hum, this is an integer will be used with values between 0 and 7, as that is what the HDL tells me. - I could replace it with a UNSIGNED that can hold values between 0 and 7, as it only needs positive numbers. - To hold the numbers between 0 and 7 I only need 3 bits. - Great! I will implement this signal as a 3-bit unsigned binary value - Because this is a 3-bit value I can update it with a 3-bit adder ... I doesn't statically inspect the rest of the code to enforce that you will only use numbers in the stated range. It also doesn't put any additional logic enforce the range as stated (e.g. clamping, or wrapping of results), you have to ensure that your design stays within the stated range. For this reason I prefer to use UNSIGNED(n downto 0 ), so I know exactly what the tools will produce. I am sure others will disagree, and prefer the higher level of abstraction, and finding ranges is very useful in simulation (as long as the "range check" option is turned on!). ... diversion... An important consideration for this is when inferring memory blocks. If you define a memory block that has 768 entries, you might end up with a physical memory block that has 1024 entries, 256 of which you might not be using. Or it might be made up of three blocks with 256 entries each, and the required logic to make it work as if it is a single memory block. So why is this important? Well, if you set the write address to an invalid index of 1023 or 768 (as only 0 to 767 are valid) you might find that you corrupt entry 511 or 256 by accident. Or maybe you won't today, depending on what the synthesis tools feel like doing and the address decode logic during the last build. The tools are designed to take as many shortcuts as possible to give you exactly what you asked for, no more and no less, with most optimized use of FPGA resources. Don't be surprised if unexpected inputs give unexpected outputs
  5. With a 10k resistance only 0.26mA will be flowing from the emiiter to the base of the transistor. Depending on the current gain of the transistor (maybe 100x) that still only gives 26mA to drive the motor. Use a 330 ohm resistor and see if that helps. That should allow allow around 10mA to pass through the base, allowing the transistor to switch around 1A. Also it is good practice to have a snubber diode over the motor, to prevent it damaging your FPGA board. You may also want to use a NPN transistor, allowing the emitter to be connected to ground, rather than the positive (regulated) power rail. This would be especially helpful if the motor is to be powered by a different supply.
  6. The PMOD connector pins are not able to provide much power - at best a few mA. You will need to add something to increase the power - either a transistor or MOSFET switch, or maybe a full H-bridge driver. Also, the voltage regulators on the FPGA is only engineered to power the FPGA and a few low power add-ons. So you will need an additional external power source to drive the motor.
  7. In general the tools will let you try anything. If you want to "ski off piste" the let you. They may warn strongly against it, or might even need you to stamp your feet a little with directives and settings, but you might have a valid need to do what you are asking. They also can only control what you do inside the FPGA. For example, if you had "output_pins <= std_logic_vector(unsigned(input_pins)+1);" and wire your outputs and inputs together you will get exactly what you have inside the chip (but a little slower). If you work with software you should all be used to this. Take this small C program: $ cat div.c #include <stdlib.h> int main(int argv, char *argc[]) { return atoi(argc[1])/0; } $ gcc -o div div.c -Wall -pedantic -O4 div.c: In function ‘main’: div.c:3:23: warning: division by zero [-Wdiv-by-zero] return atoi(argc[1])/0; ^ $ ./div 123 Floating point exception (core dumped) $ Should divide by a constant zero be a critical error? How is the compiler supposed to know if you are really doing this by accident, or are writing a program to test the behavior of divide by zero? Part of the learning curve for FPGAs is to develop a feeling for what is the "safe area" to work in, and recognize when you are leaving wandering outside of it. It is a shame that in this case you stumbled into this by accident, but you get big bonus points from me for realizing that you were in a strange & weird place, and attempting to make some sense of it before moving on. (BTW, I like playing in these areas)
  8. Sorry to have irritated you... Here is my example: - I used an unsigned datatype for the counter - I also had all bits used - the low 24 on the PMODS, the high 8 on the LEDs. - It was built for the Nexys2 board, using the latest version of ISE. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity btn_test is Port ( clk_100M : in STD_LOGIC; btnC : in STD_LOGIC; led : out STD_LOGIC_VECTOR( 7 downto 0); seg : out STD_LOGIC_VECTOR( 6 downto 0); an : out STD_LOGIC_VECTOR( 3 downto 0); dp : out STD_LOGIC; JA : out STD_LOGIC_VECTOR( 7 downto 0); JB : out STD_LOGIC_VECTOR( 7 downto 0); JC : out STD_LOGIC_VECTOR( 7 downto 0)); end btn_test; architecture Behavioral of btn_test is signal up_test : unsigned (31 downto 0) := (others => '0'); begin count_button_process_triggers: process(btnC) begin up_test <= up_test +1; end process; JA <= std_logic_vector(up_test( 7 DOWNTO 0)); JB <= std_logic_vector(up_test(15 DOWNTO 8)); JC <= std_logic_vector(up_test(23 DOWNTO 16)); led <= std_logic_vector(up_test(31 DOWNTO 24)); seg <= (others => '0'); an <= (others => '1'); dp <= '0'; end Behavioral; The constraints are almost the standard Nexys2 ones, so I won't include them. Although it produces a metric truckload of warning about combintatorial logic oops, it does produce a BIT file, and when programmed it does do as expected, but what it arguably shouldn't be doing. Without a change in state of btnC the counter is counting up. It cycles through all 32-bit values in about 5 seconds, so each addition is taking about 1.2ns (or is free-running at about 800 MHz, if you like). Or maybe it doesn't - maybe it skips some values and the lowest bits are not counting properly. But it looks as if it counts, without a clock or an event on btnC signal.
  9. I have actually done this, and the speed only partially depends on the device parameters, the biggest being propergation delay. Moving from a breadboard to hard-wired made dramatic changes in frequency (20%+) due to inductance and capacitance. Extra decoupling (which enhanced switching speed) also changed things. Supply voltage also made a big difference too.
  10. The length of the sync pulses is important, but if you know what they should be, and you have an "data enable" that is asserted during the active pixel session, then it is logically possible to regenerate the sync pulses, using the start of the active video periods and their length as a reference point. You can count the pixels and lines, working out the format (e.g. 640x480, 800x600...) then use that to see when sync periods should start and end for standard video resolutions, and then use that to add your own sync signals.
  11. On some random web post I found this: Timing recommendation #3.... 720x576 at 50Hz Modeline................ "720x576" 27,000 720 732 796 864 576 581 586 625 -hsync -vsync ... Timing recommendation #5.... 720x576 at 50Hz Modeline................ "720x576" 27,000 720 732 796 864 576 581 586 625 -hsync -vsync Because it is larger than 640x480 it should work with standard HDMI. How to interpret the numbers 27,000 is the pixel clock Horizontal 720 active pixels 732 start horizontal blanking 796 end horizontal blanking 864 total length of line. Vertical: 576 active lines 581 Start vertical blanking 586 stop vertical blanking 625 total lines. How to generate a hsync signals out of nothing The easiest way is to .... - Convert the input into three signals Y, C and a one-bit Active_Pixel (aka 'data enable') - Add a horizontal pixel counter that counts 0 to 863 when when you see the first active pixel - i.e. reset it when you see the first active pixel, otherwise leave it free-running. - You can then generate hsync when the horizontal counter is between 732 and 795 How to generate the vsync signals - detect when you have more than 144 cycles without active data (144 = 564 clocks per line - 520 active pixels per line). This lets you know when you are in the vertical blanking interval (as the horizontal blanking is 144 cycles) - then reset the line counter when you see the next active pixel, as this will be the first visible line. - increment the line counter, whenever the horizontal counter wraps from 863 back to 0/ - Generate the vsync pulse when the line counter is between 581 and 585.
  12. Hi again - sorry, busy weekend! I had a look at the IP in Digilent's GitHub (https://github.com/Digilent/vivado-library). It looks like it can be configured to support slow pixel clocks: From CLKGEN.VHD: kClkRange : natural := 1; -- MULT_F = kClkRange*5 (choose >=120MHz=1, >=60MHz=2, >=40MHz=3, >=30MHz=4, >=25MHz=5 SO to support a 27MHz Pixel clock you will need to set kCLkRange to However.... I also had a look at the standards for the video format you mentioned. It seems to have a "data" clock of 27MHz, but each Pixel has "Y" and "C" values, so the actual Pixel clock is 13MHz. It is also an interlaced format (with odd and even fields to each frame). This format is structurally incompatible, so simple direct translation is not possible. It will really need a complex project to receive this video into memory, de-interlace it, then send it out as progressive video. The timing of "standard definition" broadcast formats (PAL, NTSC...) are not compatible with DVI or HDMI...
  13. You will find a good explanation here: https://reference.digilentinc.com/nexys_vga/refmanual There is a list of timing modes at http://hamsterworks.co.nz/mediawiki/index.php/VGA_timings - hope these help. If you look around the internet you will find lots of simple VGA projects - including this one: http://www.hamsterworks.co.nz/mediawiki/index.php/Papilio_Plus/Hello_World
  14. If the video is coming from memory, using the faster pixel clocks isn't a problem just add a black border (80 pixels left and right, 60 pixels top and bottom) would be simple. If they are standards compliant all HDMI devices (both sources and sinks) "should" support 640x480 (24.something MHz pixel clock). Odds are that the PLL/DCM used by RGB2DVI to generate the clocks for the SERDES blocks isn't configured to lock onto really slow pixel clock rates below 50MHz. I've never used RGV2DVI, but if the source is included then checking out the clocking and doubling the Multiply/Divide values to keep the VCO frequency in the correct range should be all that is needed. If this does work, then just put your Y values to all three channels ( R, G & B ), and you should have a 8-bit greyscale image, without any mucking around with HDMI.
  15. The math will work (as you can expect): gray = (r * 76 + g * 150 + b * 29 + 128) >> 8; I can't see any reason that it couldn't be integrated in the HDMI-in to VGA out project, I have never looked at that project, but I suspect it will need to be implemented in a way that will fit nicely (be that an IP block, a HLS module or a VHDL or Verilog module).
  16. Hi, The "HDMI" on Fpga4fun is actually DVI-D, which is electrically compatible to HDMI but doesn't support any of the useful features like sound, colour spaces or 422 pixel formats. If you have the option, it will be quicker to use an IP block, however, if you want to implement it at a low level:. 1. A guard band added to the start of the video data - this consists of a special sequence of bytes. This is easy. 2. The HDMI "AVI infoframe" data packet.- this describes the video format as it goes over the wire, and it is in this packet that the HDMI source tells the HDMI sink if the stream is RGB444 or YCC4444 or YCC422. Building the inforpacket is quite hard - it uses a separate coding scheme layered over the low level TMDS signalling, and has ECC and if this is wrong then the HDMI sink won't be able to decode the video stream correctly. An absolute minimal HDMI output design (with only support for 3-bit colour have a look at http://hamsterworks.co.nz/mediawiki/index.php/Minimal_HDMI - but that design is not a good way to approach the your problem. You will want a proper TMDS encoding layer that supports the full range of data values to generate 24-bit images (or for YCC it will actually be 12-bits for each component).
  17. As a side note, the normal format for DVID is RGB 444 (24 bits per pixel). You get 8 bits of each component each pixel clock. If the FPGA board advertises that it supports HDMI and that it supports YCC 422, you will get: 12 bits of Y0, and 12 bits of Cb on the first pixel clock (channel 1 carries the lower four bits of Y0 and Cr) 12 bits of Y1, and 12 bits of Cr on the second pixel clock (channel 1 carries the lower four bits of Y1 and Cr) If you want to get higher greyscale depth than 12 bits you will need to use a deep color mode. In the display port 1.4 spec deep colour modes supported are 24-, 30-, 36- and 48-bits per pixel, and only RGB 444 and for YCbCr 444 are supported. Out of all the options, only 48-bits per pixel YCbCr gives you a 16-bit Y value, but it also doubles your data rate, making it not really usable with most low end FPGA dev boards - with generic I/O SERDES rated to about 1.2Gb/s you only use up to a 60MHz pixel clocks at 48 bits per pixel - not even enough for 720p images. So as an upshot, if the best bet might just be to stick with RGB 444 on the interface using the existing solutions, and then do the transform into YCC within the FPGA design...
  18. hamster

    FPGA audio - ADC and DAC

    If clocking is your problem, with a MMCME2_BASE with a 100MHz clock you can get to: 100,000,000Hz * 7.25 / 59.0 = 12,288,135 Hz Out by about 11 parts per million - The 100MHz oscillator on the Arty A7 (ASEM1-1 0 0.0 0 0MHZ-LC-T) is +/-50 ppm, so maybe nobody will really notice.
  19. hamster

    FPGA audio - ADC and DAC

    Although it is VHDL, and mostly around configuration of the CODEC, this project takes line in and sends it out line out on a STGL5000 CODEC that I got off of Tindie that is for the Raspberry Pi. http://hamsterworks.co.nz/mediawiki/index.php/STGL5000 It uses the clock provided by the codec board.
  20. There are a couple of ideas used to divide digital logic designs into different classes. Combinatorial vs Sequential Combinatorial logic is pretty much any logic with outputs that should responds 'instantly' to changes in the input, and where the output is a pure function of the present input only (i.e. has no internal state) vs Sequential logic is logic with output depends not only on the present value of its input signals but also the sequence of past inputs (i.e. it has internal state). Most FPGA designs (if not all!) fall into this category. Synchronous vs Asynchronous Synchronous logic updates on the edge of a clock, which provides the timing information. Most FPGA designs fall into this category. Asynchronous logic updates the outputs as the input changes - the changes of the input signals provide the timing information. These designs use things like latches and subtle timing behavior to function properly, and are not usually compatible with FPGAs. How this relates to VHDL concurrent statements vs processes VHDL concurrent statements generally describing asynchronous logic, and processes are usually describing synchronous logic - but not this is not always true! Complex async logic can be best expressed in processes,as you can use "if" and "case" statements - you can tell these because of the long sensitivity lists, rather than being sensitive to just a single clock signal. And with statements like "Q <= D when rising_edge(clk);" you can make a concurrent statement implement synchronous logic, and squirrel them away where others are not expecting to see them!
  21. You might be using "FSM" when you mean "combinatorial logic". :-)
  22. This is the warning that matters: "signal 'up_test' is read in the process but is not in the sensitivity list" What has happened is the tools have detected that you read the value of "up_test" in the process, assumes that you have made an error, and helpfully added it to the process's sensitivity list. This is because for any async logic in processes all signals that are used in the process should be included in the sensitivity list. Were "up_test" included in the sensitivity list you would get exactly the observed behavior (although now any simulations would hang/break... sigh). If this is the right thing for the tools to do is an open question - sometimes it is, sometimes it isn't. Throwing an error rather than a warning would break existing code bases... issuing warnings lets these sorts of issues slip through. By "you haven't defined is some way to filter out the changes of BTN", Ignore me - I was just waffling on to allude that you need to use "rising_edge()" somewhere to control the timing of when "up_test" gets updated.
  23. As a side issue, I recently did something that had similar data requirements - capturing 2-bit samples at 16,386MHz (32Mb/s) for an extended period of time (many minutes) I used an older NEXYS2 board because it has the Digilent EPP interface, that can stream at well over this speed. - A simple HDL design captured the data, wrote it into a FIFO with a sequence counter bit so I could detect dropped data - Some more HDL read the FIFO, and sent the data up the EPP interface to the host PC. On the PC it then: - Allocated a large buffer (a couple of GB IIRC) - Cleared the buffer to force it into memory, so it woudn't stall - Streamed in the data from the EPP interface - Once data was in buffer on the PC it was written to the slow disk SATA I had to buffer it in memory, because a small delay on the PC end would cause the FIFO on the FPGA board to overrun. I could have most likely used a second thread to write the data in real time if I needed to. It ended up being a very small simple design when compared to what you are contemplating. Have a look at https://github.com/hamsternz/Full_Stack_GPS_Receiver/tree/master/misc
  24. I have a differing view from @Zygot's You are right - the counter shouldn't be running continuously, If you follow the language spec to the letter, your counter should change any time the state of BTN changes. That is what you should get in simulation. However, what you haven't defined is some way to filter out the changes of BTN, such that the counter only incremented with some of the possible state changes (.e.g a "rising_edge()" clause). When the synthesis tools try to convert your designs into hardware they are looking for either clocks or async resets or clocks to act as triggers for changes in state. The design has neither of these - it can't see that BTN should act as a dual-edged clock, so along with some warnings (I hope it gives warnings, heck, the tools give warnings for everything!) it just gives you an adder, with nothing controlling the timing of when up_test is updated. The synthesis guys will are that this is what you want and this is what you asked for, and they will also argue that the sensitivity list is just a hint for simulation.... What you really want is something like: btn_clk_proc : process (btn) begin if rising_edge(btn) then test <= test+1; end if; end process; ... but then that leads onto discussions of switch bounce, routing delays and metastabiliy.
  25. It seems easy on the surface of it, but - The different channels have different guard band values - You need to work out what blanking and sync signals you need to assert during the guard bands and data packet guard bands - The HDMI pixel data might be in "Studio level" (16-239) rather than full range (0-255) - The video data might be in YCrCb 444 rather than RGB 444 format. (The RGB 444 means that for each four pixels there are 4 R values, 4 G values and 4 B values) - The video data might be in YCrCb 422, where you have 12-bit values, and you get four Y (brghtness) but only two Cr or Cb values per for pixels. (which is more like TV video formats) I made an attempt at decoding this, and it seems to work ok. You might be able to find any hints you need at my project: https://github.com/hamsternz/Artix-7-HDMI-processing/blob/master/src/hdmi_input.vhd but the source for all knowledge is the HDMI specification - find it by searching for "hdmi specification 1.2a filetype:pdf" or "hdmi specification 1.4 filetype:pdf" - e.g. http://read.pudn.com/downloads72/doc/261979/HDMI_Specification_1.2a.pdf