6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Apr 25, 2024 1:58 pm

All times are UTC




Post new topic Reply to topic  [ 53 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: CPLD Driven color VGA
PostPosted: Wed Nov 29, 2017 12:30 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
I've been playing around with some CPLDs and thought I'd try to build a simple color VGA circuit for my 6502 system.
The code fits within either a Xilinx XL9572XL (68/72 Macrocells used) or an Altera MAX7064S (58/64 Macrocells used)

It's not as full featured as the CRTC because there doesn't seem to be enough space in the device to fit the registers required, so no hardware scrolling with this one but I plan to move up to a 128 macrocell cpld to achieve that later.

The current circuit is pictured here without the CPLD included in the diagram:
Memory is divided into Even (Character data) and Odd (Color data) addresses from the MPU side
Image

And the VHDL
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity vga6502 is

    port
    (
        clk       : in std_logic;
        sl        : out std_logic;
        latch      : out std_logic;
        reset     : in std_logic;
        ma        : out std_logic_vector(11 downto 0);
        ra        : out std_logic_vector(3 downto 0);
        e         : out std_logic;
        hsync     : out std_logic;
        vsync     : out std_logic
    );

end entity;

architecture behavioral of vga6502 is
signal CLK8: std_logic := '0';
signal CLKDIV: integer range 0 to 3;
signal SRDIV: std_logic_vector(2 downto 0);

constant H_TOT: integer range 0 to 100 := 100;
constant H_FP:  integer := 2;
constant H_BP:  integer := 6;
constant H_SW:  integer := 12;

signal H_CNTR:  integer range 0 to 100;
signal H_END:   std_logic := '0';
signal H_BLANK: std_logic := '0';

constant V_TOT: integer := 449;
constant V_FP:  integer := 12;
constant V_SW:  integer := 2;
constant V_BP:  integer := 35;

signal V_CNTR: integer range 0 to 525;
signal V_BLANK: std_logic := '0';

signal CH_CNTR: integer range 0 to 4095;
signal RW_REG:  integer range 0 to 4095;
signal CH_CLK:  std_logic := '0';
signal SL_CNTR: integer range 0 to 15;

begin

e <= (V_BLANK OR H_BLANK);

---
--- Clock Divider
--- Divides 25.175 Mhz Pixel clock by 8, i.e to load one character every 8 clocks
---
charclk:
process(clk, reset)
    begin
    if reset = '1' then
        CLKDIV <= 0;
        elsif (rising_edge(clk)) then
        if (CLKDIV = 3) then
            CLK8 <= NOT(CLK8);
            CLKDIV <= 0;
        else
            CLKDIV <= CLKDIV + 1;
        end if;
     end if;
end process;

--
-- Horizontal
--

H_cnt:
process(clk8, reset)
begin
    if (reset = '1') then
         H_CNTR <= 0;
    elsif rising_edge(clk8) then
        if (H_CNTR = (H_TOT - 1)) then
            H_END <= '1';
            H_CNTR <= 0;
        else
            H_END <= '0';
            H_CNTR <= H_CNTR + 1;
        end if;
    end if;
end process;

H_display:
process(clk8)
begin
    if rising_edge(clk8) then
        if (H_CNTR >= (H_SW + H_BP)) AND (H_CNTR < (H_TOT - H_FP)) then
            H_BLANK <= '0';
        else
            H_BLANK <= '1';
        end if;
    end if;
end process;

H_sync:
process(clk)
begin
    if rising_edge(clk) then
        if (H_CNTR < H_SW) then
            HSYNC <= '0';
        else
            HSYNC <= '1';
        end if;
    end if;
end process;

---
--- Vertical
---

V_cnt:
process (H_END, reset)
begin
    if (reset = '1') then
        V_CNTR <= 0;
    elsif falling_edge(H_END) then
        if (V_CNTR < V_TOT) then
            V_CNTR <= V_CNTR + 1;
        else
            V_CNTR <= 0;
        end if;
    end if;
end process;

V_display:
process(H_END)
begin
    if falling_edge(H_END) then
        if (V_CNTR >= (V_SW + V_BP)) AND (V_CNTR < (V_TOT - V_FP)) then
            V_BLANK <= '0';
        else
            V_BLANK <= '1';
        end if;
    end if;
end process;

V_sync:
process(H_END)
begin
    if falling_edge(H_END) then
        if (V_CNTR < V_SW) then
            VSYNC <= '1';
        else
            VSYNC <= '0';
        end if;
    end if;
end process;

---
--- Scanline Counter
--- Outputs RA row address to Char Rom
---

SL_cnt:
process(H_END, reset)
begin
    if (reset = '1') then
        SL_CNTR <= 0;
    elsif falling_edge(H_END) then
        if (SL_CNTR = 15) or (V_BLANK = '1') then
            SL_CNTR <= 0;
        else
            SL_CNTR <= SL_CNTR + 1;
        end if;
    end if;
end process;

RA <= std_logic_vector(to_unsigned(SL_CNTR, RA'length));

---
--- Char Row Clock, increment row count every 16 scanlines
---
CHCLK:
process(SL_CNTR)
begin
    if (SL_CNTR = 15) then
        CH_CLK <= '1';
    else
        CH_CLK <= '0';
    end if;
end process;


RW_cnt:
process(reset,CH_CLK,V_BLANK)
begin
    if (reset = '1') OR (V_BLANK = '1') then
        RW_REG <= 0;
    elsif falling_edge(CH_CLK) then
        RW_REG <= RW_REG + 80;
    end if;
end process;

---
--- Char Counter
--- Generates linear memory addresses
---

C_cnt:
process(reset,CLK8)
begin
    if (reset = '1') then
        CH_CNTR <= 0;
    elsif rising_edge(CLK8) then
        if (H_CNTR >= (H_SW + H_BP)) AND (H_CNTR < (H_TOT - H_FP)) then
            CH_CNTR <= CH_CNTR + 1;
        else
            CH_CNTR <= RW_REG;
        end if;
    end if;
end process;

MA <= std_logic_vector(to_unsigned(CH_CNTR, MA'length));

---
--- Shift Register control
--- load the shift register every 8 clocks
---

SR_ctrl:
process(reset,clk)
begin
    if reset = '1' then
        SRDIV <= (others => '0');
    elsif rising_edge(clk) then
        if (H_CNTR >= (H_SW + H_BP)) AND (H_CNTR <= (H_TOT - H_FP)) then
            SRDIV <= SRDIV + '1';
        else
            SRDIV <= (others => '0');
        end if;
    end if;
end process;

--- Load shift register
SL <= '0' when (SRDIV (2 downto 0) = "000" AND (CLK = '1')) else '1';
--- Load color latch
LATCH <= '0' when (SRDIV (2 downto 0) = "111" AND (CLK = '1')) else '1';

end behavioral;


As a VHDL noob there's probably a heap of things I can improve on, please let me know if you've got any tips!

Interestingly the ROM is so slow (150ns) that to get it working I have to load the shift register just before the rom is pointed to a new address
As a matter of fact if you look at the timing from the RTL Simulation you can see that the shift register is loaded at the same time the MA output changes, presumably the SRAM and ROM delays are just long enough for this to work...
Image
SL = Shift register Load
E = Video output enable

I could load the shift register sooner than that by a couple of clocks but that'd push the first X pixels off the left hand side of the screen. since the horizontal count is in characters rather than pixels I can only really load shift register right as the address is changing (and this is why I need to latch the color data at around the same time). how was this done with CRTC based systems?

This results in an 80x30 display with 16 colors foreground/background that works almost perfectly. At the moment I don't have the second SRAM to store the color data so I've been testing by connecting MA0-7 to the inputs of the color latch.

The only problem I've had is that I can't get the color to sync up with the characters perfectly
Basically the color data seems to change just after the character does, resulting in the first pixel of the character being the wrong color. tuning the latch output to load sooner/later just pushes it over one side or the other. never matching up perfectly with the character data

I'm going to see what happens when I actually source the color data from RAM, as well as replacing the HC logic with AC logic to tighten things up a bit.
I probably need to add a second latch after the color mux too?

Any pointers would be appreciated!


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 29, 2017 2:12 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
It's often useful to think in terms of how the input relates to the output of any part of the design.
Take the first section of your design.

Code:
---
--- Clock Divider
--- Divides 25.175 Mhz Pixel clock by 8, i.e to load one character every 8 clocks
---
charclk:
process(clk, reset)
    begin
    if reset = '1' then
        CLKDIV <= 0;
        elsif (rising_edge(clk)) then
        if (CLKDIV = 3) then
            CLK8 <= NOT(CLK8);
            CLKDIV <= 0;
        else
            CLKDIV <= CLKDIV + 1;
        end if;
     end if;
end process;



You could change CLKDIV to std_logic_vector and rewrite the block as:
Code:
signal CLKDIV: std_logic_vector(2 downto 0);

.
.
.
.

process(clk, reset)
    begin
    if reset = '1' then
        CLKDIV <= 0;
        elsif (rising_edge(clk)) then
            CLK8 <= CLKDIV(2);
            CLKDIV <= CLKDIV + 1;
        end if;
     end if;
end process;


Depending on the design though, sometimes a single large counter (counting the length of a full video line) can actually work out to use less in the way of hardware resources, as many other signals can be picked up from the one counter. CLK(8) would always be bit(2) of the line counter for instance.


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 29, 2017 3:17 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
It probably best to try an avoid the use of "IEEE.STD_LOGIC_UNSIGNED.ALL", and never use it along side "ieee.numeric_std" as they can conflict (they perform the same function, though differently). Despite the name, "IEEE.STD_LOGIC_UNSIGNED.ALL" is not an IEEE standard library, and was made by Synopsis, and may behave differently with different vendors tools.

More info on the topic:
http://insights.sigasi.com/tech/depreca ... aries.html
https://stackoverflow.com/questions/457 ... umeric-std
http://vhdlguru.blogspot.com.au/2010/03 ... erred.html


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 29, 2017 4:44 am 
Offline

Joined: Wed Aug 16, 2017 5:35 am
Posts: 10
May be something from it could be useful for You.


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 29, 2017 6:48 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
Sorry, I somehow missed the main point of the question :(

LIV2 wrote:
The only problem I've had is that I can't get the color to sync up with the characters perfectly
Basically the color data seems to change just after the character does, resulting in the first pixel of the character being the wrong color. tuning the latch output to load sooner/later just pushes it over one side or the other. never matching up perfectly with the character data


What happens if you delay the character data by a pixel to match the delay in the colour?
I'm not sure I'm understanding the design 100% so I may be typing rubbish, but...

You could try a delay on SRDIV (if this is what's clocking the data out) by changing:
Code:
--- Load shift register
SL <= '0' when (SRDIV (2 downto 0) = "000" AND (CLK = '1')) else '1';

Into:
Code:
process(reset,clk)
begin
    if rising_edge(clk) then
        SRDIV_d <= SRDIV;
    end if;
end process;

--- Load shift register
SL <= '0' when (SRDIV_d (2 downto 0) = "000" AND (CLK = '1')) else '1';


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 02, 2017 12:05 pm 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Thanks Cray Ze, I had tried delaying the character pixel as you said but it didn't solve the problem.
I'll also go through and remove IEEE.STD_LOGIC_UNSIGNED from my code thanks for that tip too!

After adding the extra SRAM for the color things look a little better but there's still a little problem with the first pixel of each character as pictured below
Interestingly it's only on the edge of some colors not sure why. but I'm almost certain the issue is actually due to the propogation delay of the 74HC273 which is 19ns keeping in mind that the width of each pixel at a 25mhz pixel clock is 40ns.

So I've ordered a couple of 74AC273s to see if that fixes it (fingers crossed!) In the meantime I'll clean up the VHDL as per your helpful suggestions


Attachments:
Photo 2-12-17, 10 49 13 pm (1).jpg
Photo 2-12-17, 10 49 13 pm (1).jpg [ 1.97 MiB | Viewed 8368 times ]
Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 3:20 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Replacing the 74HC273 with a 74AC273 solved the problem, though it didn't work properly until I added a 1K resistor between the CP input and the CPLD, Breadboard noise? I'm not sure whether to add this to the circuit when I go to PCB?

Switching the 74HC157 to a 74AC157 results in no text just the background color so I presume it isn't switching for some reason that is beyond me, I'll see what happens when I move to a PCB but it seems to work with the 74HC157 just fine anyway.

One last thing is that the characters are stretched because I'm using a 25Mhz oscillator instead of a 25.175 MHz as specified by the VGA spec for 640x480@60Hz and it seems that the timing difference causes my monitor to detect the mode as 720x400. I've ordered a 25.175 MHz oscillator.

Next step is to get it made into a 4 layer PCB so that I can eliminate a lot of the noise, even though it works on the breadboard there is some visible noise.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 4:39 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
I've seen 25MHz used for 640x480 many times and have used it myself without the mode detection issues. So, ruling out a
very fussy monitor, it might be an idea to double check the timing parameters in your design. Horizontal looks a bit odd
at first glance but I haven't had a detailed look.

Good 640x480@60Hz timings to compare against.
http://tinyvga.com/vga-timing/640x480@60Hz

There is this bit near the top of your code that doesn't quite look right. Defining a range doesn't fit with what a 'constant' is.
There is likely a warning message in the synthesizer output telling you what the tool decided to do.

Code:
constant H_TOT: integer range 0 to 100 := 100;


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 4:46 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Thanks, I'll fix up that constant
I've also removed "IEEE.STD_LOGIC_UNSIGNED.ALL" too

Horizontal timing looks right to me, the horizontal timings are all from that page but divided by 8 as the horizontal counter counts characters rather than pixels.
Looks like I royally stuffed up the vertical timings though... At some point I was doing 640x400 but it would appear I forgot to switch the timings back!


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 5:04 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
That might explain the confused monitor :D


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 5:27 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
I also found another mistake
Code:
V_cnt:
process (H_END, reset)
begin
    if (reset = '1') then
        V_CNTR <= 0;
    elsif falling_edge(H_END) then
        if (V_CNTR < V_TOT) then
            V_CNTR <= V_CNTR + 1;
        else
            V_CNTR <= 0;
        end if;
    end if;
end process;


Namely "if (V_CNTR < V_TOT) then"
Because the counter starts at 0 and not 1, this was extending the frame by 1 line. I could have changed V_TOT to 524 but to save confusion later I did the following instead

Code:
V_cnt:
process (H_END, reset)
begin
    if (reset = '1') then
        V_CNTR <= 0;
    elsif falling_edge(H_END) then
        if (V_CNTR = (V_TOT-1)) then
            V_CNTR <= 0;
        else
            V_CNTR <= V_CNTR + 1;
        end if;
    end if;
end process;


Changing it to compare V_TOT-1 fixed the timing (At least from the RTL Sim, I won't be able to test with the real thing for a couple of weeks)
This also has a nice benefit of reducing the macrocell usage which went from 61 down to 58. probably because of the change in the way the comparison works?

Hopefully I can find a couple of other things to optimize :)

Current code is as follows:
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity vga6502 is

    port
    (
        clk       : in std_logic;
        sl        : out std_logic;
        latch      : out std_logic;
        reset     : in std_logic;
        ma        : out std_logic_vector(11 downto 0);
        ra        : out std_logic_vector(3 downto 0);
        e         : out std_logic;
        hsync     : out std_logic;
        vsync     : out std_logic
    );

end entity;

architecture behavioral of vga6502 is
signal CLK8:   std_logic := '0';
signal CLKDIV: integer range 0 to 3;
signal SRDIV:  unsigned (2 downto 0);

constant H_TOT: integer := 100;
constant H_FP:  integer := 2;
constant H_BP:  integer := 6;
constant H_SW:  integer := 12;

signal H_CNTR:  integer range 0 to 100;
signal H_END:   std_logic := '0';
signal H_BLANK: std_logic := '0';

constant V_TOT: integer := 525;
constant V_FP:  integer := 10;
constant V_SW:  integer := 2;
constant V_BP:  integer := 33;

signal V_CNTR: integer range 0 to 525;
signal V_BLANK: std_logic := '0';

signal CH_CNTR: integer range 0 to 4096;
signal RW_REG:  integer range 0 to 4096;
signal CH_CLK:  std_logic := '0';
signal SL_CNTR: integer range 0 to 15;

begin

e <= (V_BLANK OR H_BLANK);

---
--- Clock Divider
--- Divides 25.175 Mhz Pixel clock by 8, i.e to load one character every 8 clocks
---
charclk:
process(clk, reset)
    begin
    if reset = '1' then
        CLKDIV <= 0;
        elsif (rising_edge(clk)) then
        if (CLKDIV = 3) then
            CLK8 <= NOT(CLK8);
            CLKDIV <= 0;
        else
            CLKDIV <= CLKDIV + 1;
        end if;
     end if;
end process;

--
-- Horizontal
--

H_cnt:
process(clk8, reset)
begin
    if (reset = '1') then
         H_CNTR <= 0;
    elsif rising_edge(clk8) then
        if (H_CNTR = (H_TOT - 1)) then
            H_END <= '1';
            H_CNTR <= 0;
        else
            H_END <= '0';
            H_CNTR <= H_CNTR + 1;
        end if;
    end if;
end process;

H_display:
process(clk8)
begin
    if rising_edge(clk8) then
        if (H_CNTR >= (H_SW + H_BP)) AND (H_CNTR < (H_TOT - H_FP)) then
            H_BLANK <= '0';
        else
            H_BLANK <= '1';
        end if;
    end if;
end process;

H_sync:
process(clk)
begin
    if rising_edge(clk) then
        if (H_CNTR < H_SW) then
            HSYNC <= '0';
        else
            HSYNC <= '1';
        end if;
    end if;
end process;

---
--- Vertical
---

V_cnt:
process (H_END, reset)
begin
    if (reset = '1') then
        V_CNTR <= 0;
    elsif falling_edge(H_END) then
        if (V_CNTR = (V_TOT-1)) then
            V_CNTR <= 0;
        else
            V_CNTR <= V_CNTR + 1;
        end if;
    end if;
end process;

V_display:
process(H_END)
begin
    if falling_edge(H_END) then
        if (V_CNTR >= (V_SW + V_BP)) AND (V_CNTR < (V_TOT - V_FP)) then
            V_BLANK <= '0';
        else
            V_BLANK <= '1';
        end if;
    end if;
end process;

V_sync:
process(H_END)
begin
    if falling_edge(H_END) then
        if (V_CNTR < V_SW) then
            VSYNC <= '1';
        else
            VSYNC <= '0';
        end if;
    end if;
end process;

---
--- Scanline Counter
--- Outputs RA row address to Char Rom
---

SL_cnt:
process(H_END, reset)
begin
    if (reset = '1') then
        SL_CNTR <= 0;
    elsif falling_edge(H_END) then
        if (SL_CNTR = 15) or (V_BLANK = '1') then
            SL_CNTR <= 0;
        else
            SL_CNTR <= SL_CNTR + 1;
        end if;
    end if;
end process;

RA <= std_logic_vector(to_unsigned(SL_CNTR, RA'length));

---
--- Char Row Clock, increment row count every 16 scanlines
---
CHCLK:
process(SL_CNTR)
begin
    if (SL_CNTR = 15) then
        CH_CLK <= '1';
    else
        CH_CLK <= '0';
    end if;
end process;


RW_cnt:
process(reset,CH_CLK,V_BLANK)
begin
    if (reset = '1') OR (V_BLANK = '1') then
        RW_REG <= 0;
    elsif falling_edge(CH_CLK) then
        RW_REG <= RW_REG + 80;
    else
        RW_REG <= RW_REG;
    end if;
end process;

---
--- Char Counter
--- Generates linear memory addresses
---

C_cnt:
process(reset,CLK8)
begin
    if (reset = '1') then
        CH_CNTR <= 0;
    elsif rising_edge(CLK8) then
        if (H_CNTR >= (H_SW + H_BP)) AND (H_CNTR < (H_TOT - H_FP)) then
            CH_CNTR <= CH_CNTR + 1;
        else
            CH_CNTR <= RW_REG;
        end if;
    end if;
end process;

MA <= std_logic_vector(to_unsigned(CH_CNTR, MA'length));

---
--- Shift Register control
--- load the shift register every 8 clocks
---

SR_ctrl:
process(reset,clk)
begin
    if reset = '1' then
        SRDIV <= (others => '0');
    elsif rising_edge(clk) then
        if (H_CNTR >= (H_SW + H_BP)) AND (H_CNTR <= (H_TOT - H_FP)) then
            SRDIV <= SRDIV + 1;
        else
            SRDIV <= (others => '0');
        end if;
    end if;
end process;

--- Load shift register
SL <= '0' when (SRDIV = "0" AND (CLK = '1')) else '1';
--- Load color latch
LATCH <= '1' when (SRDIV = "0" AND (CLK = '1')) else '0';

end behavioral;


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 6:35 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
LIV2 wrote:
Hopefully I can find a couple of other things to optimize :)


Think about the transition from "Back porch" to "Front porch", and what happens with other signals at the time,
the answer is likely "Not Much".

The optimization: If not visible, porch.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 6:59 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
So something like
Code:
If H_CNTR = H_BP then:
  H_BLANK <= '0';
elsif H_CNTR = (H_TOT - H_FP) then:
  H_BLANK <= '1';
else
  H_BLANK <= H_BLANK;
end if;

And the same for V porches etc?


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 7:28 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
I haven't had a good look at the above change yet, but before you go to far.

From a signal point of view you can move all the porch cycles to the back porch.
BP would be you current BP + FP values.
FP would become 0

You'll see more optimizations from that point.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 05, 2017 1:21 pm 
Offline
User avatar

Joined: Wed Aug 17, 2005 12:07 am
Posts: 1207
Location: Soddy-Daisy, TN USA
There is something I'm confused about...my general ignorance of VHDL...

But on your divide-by-8 logic:

Code:
...
signal CLKDIV: integer range 0 to 3;
...
---
--- Clock Divider
--- Divides 25.175 Mhz Pixel clock by 8, i.e to load one character every 8 clocks
---
charclk:
process(clk, reset)
    begin
    if reset = '1' then
        CLKDIV <= 0;
        elsif (rising_edge(clk)) then
        if (CLKDIV = 3) then
            CLK8 <= NOT(CLK8);
            CLKDIV <= 0;
        else
            CLKDIV <= CLKDIV + 1;
        end if;
     end if;
end process;
...


If CLKDIV an integer value from 0-3 (4 values) then how does

Code:
if (CLKDIV = 3) then


divide it by 8? If CLKDIV were 4 bits then I could see that working as 3 bits = 8.

Thanks for any insight.

_________________
Cat; the other white meat.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 53 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: