I'm an FPGA beginner and have trouble understanding how VGA control
signals and VGA interact, and how to correctly generate VGA control
signals (with Verilog) for more complicated specifications:
Seemingly, the low portions in horizontal- and vertical- sync signals
correspond to transitioning from one row to the next, and transitioning
from the bottom-right corner to the upper-left corner, respectively. But
is the VGA "controlled" by those low signals? Do those low signals
"tell" the VGA to switch to next row or jump back to the starting point?
Are the back porch and front porch there to satisfy setup time and
hold time? Are the durations of porches given in VGA timing table only
required minima (i.e. can I set the porches to be much longer than the
given values in the timing table?)
This is what confuses me the most: From the two continuous
horizontal- and vertical- sync signals, how on earth does the VGA know
(or do I know) exactly which point on screen it is displaying? If timing
is the only factor, does that mean I must pay a lot of attention to
match RPG control signals and h-sync and v-sync signals perfectly? If
the answer is yes, then I have even more problems which I can only
describe using my assignment as an example:
In this assignment we use a built-in 50MHz clock of an FPGA (Spartan starter board) and the pixels of the VGA is specified to be 800x600. The framerate is specified to be 72Hz.
The VGA timing table gives the following sync signal structures:
h-sync:
| 0---back-porch(104)---103 | 104---display(800)---903 | 904---front-porch(16)---919 | 920__pulse width(120)__1039 |
v-sync:
| 0---back-porch(23)---22 | 23---display(600)---622 | 623---front-porch(37)---659 | 660__pulse width(6)__665 |
This seems to mean that for each pixel in a row on screen I spend 1
clock cycle (20ns) on it. However, for many complicated cases, I would
want to control the color of a pixel depending on its location on screen
and perhaps a lot of additional conditions such as the relation of
current position with another location, certain states, etc. Now, if the location of the pixel depends on horizontal and vertical pixel counters, and the color depends further on the location, how can I match them in time? Also, what if my logic has to spend more than 20ns to decide the color of a pixel? Will that completely crash the image on the VGA screen?
Actually I've somehow completed my assignment, but I find my code messy
and I totally have no idea why it worked:
For example, a portion of the assignment required us to show a star that
changes its color every 0.5sec. My implementation looks like:
//----------------pixel counters----------------
always#(posedge CLK or posedge RESET) begin
if(RESET) h_count <= 11'd 0;
else if (h_count >= 11'd 1039) h_count <= 11'd 0;
else h_count <= h_count + 11'd 1;
end
always#(posedge CLK or posedge RESET) begin
if(RESET) v_count <= 10'd 0;
else if (v_count >= 10'd 665) v_count <= 10'd 0;
else if (h_count == 11'd 1039) v_count <= v_count + 10'd 1;
else v_count <= v_count;
end
//----------------h- and v- sync----------------
always#(posedge CLK or posedge RESET) begin
if(RESET) VGA_HSYNC <= 1'b 0;
else VGA_HSYNC <= (h_count >= 11'd 0) & (h_count <= 11'd 919);
end
always#(posedge CLK or posedge RESET) begin
if(RESET) VGA_VSYNC <= 1'b 0;
else VGA_VSYNC <= (v_count >= 10'd 0) & (v_count <= 10'd 659);
end
//----------------a frame counter and a flag----------------
always#(posedge CLK or posedge RESET) begin
if(RESET) frame_count <= 6'd 0;
else if (frame_count >= 6'd 49) frame_count <= 6'd 0;
else if(v_count == 10'd 665) frame_count <= frame_count + 6'd 1;
else frame_count <= frame_count;
end
always#(posedge CLK or posedge RESET) begin
if(RESET) color_flag <= 1'd 0;
else if (frame_count == 6'd 49) color_flag <= ~(color_flag);
else color_flag <= color_flag;
end
//----------------RGB control----------------
always#(posedge CLK or posedge RESET) begin
if(RESET) VGA_RGB <= 3'b 000;
else if(display) begin //display is high when counters in valid range
casez({tree, star, snow}) //these are outputs from submodules that decides the "shapes" of objects on screen
3'b ??1: VGA_RGB <= 3'b 111; //white snow
3'b ?10: VGA_RGB <= (color_flag) ? (3'b 110) : (3'b 111);
//switching between yellow and white
3'b 100: VGA_RGB <= 3'b 010; //green tree
default: VGA_RGB <= 3'b 001; //blue background
endcase
end
else VGA_RGB <= 3'b 000; //for transitions
end
It seems to me that my h_count and v_count directly decides my VGA_HSYNC and VGA_VSYNC. But my VGA_RGB depends at least on color_flag, which further depends on frame_count, which depends on h_count and v_count. Shouldn't that cause delay of a few clock cycles? The code was synthesizable and did produced what I wanted to display. But how on earth did my VGA_RGB sync with VGA_HSYNC and VGA_VSYNC in time??? Am I overthinking this issue? Or was I just lucky? What did I miss?
Most of your questions can be explained by the fact that VGA is an analog standard which was originally designed to run on analog devices. The h-sync and v-sync pulses simply trigger their respective deflection coils back to their start positions while the front and back porches account for the fact that the beam starts and ends outside the visible portion of the screen.
With respect to accuracy, it's better than it used to be: sending a badly timed VGA signal to an analog monitor in years-gone-by could actually damage it. That's all changed now with LCDs etc whose drive circuits are able to detect and display a wide range of resolutions at arbitrary refresh rates. In my experience though the amount of leeway you have is smaller than you'd think and is very dependent on the make and model of the display device...many of them even list slightly different timings in their user manuals! If you want to be sure that your circuit will work on the equipment that your tester runs it on then you should stick to one of the "official" resolutions as accurately as you can.
As far as per-pixel timing goes yes, an 800x600x72Hz signal needs a 50MHz clock and you thus have 20nS in which to fetch your pixel data (that said I'm not 100% sure your sync and porch timings are correct, they're different to the ones at VGA Timings which I've used successfully myself in the past). If 20nS isn't enough then you'll need to use multiple circuits e.g. one for odd pixels and another for evens. Alternatively you can implement pipeline stages, e.g. for the pixel you output at cycle X you read its value from ROM at cycle X-1 and calculate the address to read at cycle X-2. Another trick I've used in the past is to double-buffer the display with 2 lines of RAM i.e. on any given line you are drawing directly from one buffer whilst simultaneously writing to the next; this gives you more time to render each line but typically adds the additional complexity of separate clock domains between rendering and display.
Related
I have a question about using timers and clocks in Verilog. I want to set up a custom reg to compare to an accumulator, which will control the state of an LED. The board uses inverse logic, so 0 is high on the LED. There are a few concepts I just need some clarification on. The clock is 100 MHz.
always #(posedge clk100 or negedge reset_)
begin
cust_LED_counter <= (cust_LED_counter<cust_LED_timer) ? cust_LED_counter + 1'b1 : 16'd0;
cust_LED_timer1 <= (cust_LED_counter == cust_LED_timer);
if(!reset_)
begin
cust_LED1 <= 'b0;
cust_LED_timer <= 'd0;
cust_LED_timer1 <= 'd0;
end
else
begin
cust_LED1 <= ~cust_LED_timer1;
end
end
For the accumulator, what is the action that resets it and allows for blinking to happen? Would it not hit the cust_LED_timer value and stay at that high reading?
I think I'm misunderstanding how a FPGA clock operates. Assuming this would cause a blinking action in the LED, it would mean some timer hit the upper limit and reset; however, I'm not sure if this would take place in the counter portion of the code, or instead would occur where the clock/reset is defined.
Also, based on how this layout looks it wouldn't be a uniform blink, in terms of equal time on and off. Is there a way to implement such a system for custom input?
Here's a simple module that should blink the LED with a 50-50 duty cycle for an arbitrary number of clocks (up to 2^26)
module blink(input clk, input rst, input [25:0] count_max, output LED);
reg [25:0] counter, next_count;
assign LED = counter < count_max >> 1;
always #(posedge clk or posedge rst)
begin
if (rst)
counter <= 0;
else
counter <= next_count;
end
always #* begin
if (counter < count_max - 1)
next_count = counter + 1;
else
next_count = 0;
end
endmodule // blink
Let me know if this doesn't compile! I don't have a verilog compiler where I'm writing this from at the moment!
I'm trying to write a RTL model in which I monitor independent clock sources. These clock sources can have variable frequency (range 5 to 50MHz)
Let us say clk1 and clk2. I'm trying to drive a signal 'toggle' which is set '1' at every posedge of clk1 and is set to '0' at every negedge of clk2. I'm having trouble realizing this model.
I tried using 1 flop triggered at the positive edge of clk1 with inputs of this flop tied to 'high' and another flip flop triggered at the negative edge of clk2 with input tied to 'low'. I sent these outputs to a mux, but I have trouble figuring out how to drive the select signal of this mux
Here is my code snippet :
always_ff #(posedge clk1 or rstb) begin
if(!rstb) begin
flop1_out <= 0;
end else begin
flop1_out <= 1;
end
end
always_ff #(negedge clk2) begin
flop2_out <= 0;
end
assign toggle = sel ? flop1 : flop2;
So, as of now nothing is driving sel and trying to figure this out is where I'm having trouble
If I try to drive the same signal (toggle) from 2 different clock sources, I get an error saying that multiple drivers found for signal toggle, which makes sense.
Please let me know if you have any suggestions
EDIT: fixed a typo and removed rstb from the sensitivity list for flop2
assign rstn = clk2;
always # (posedge clk1 or negedge rstn)
if (~rstn)
toggle = 1'b0;
else
toggle <= 1'b1;
note: depending on the clock frequency and insertion delay relationships this circuit may become metastable. if you can tolerate delay, add a synchronizer on the output. better yet, if you can tolerate distortion, add a reset synchronizer on clk2 to clk1mx, where clk1mx is synchronous to clock1 but x times faster.
I'm trying to find the mid-point between hsync pulses in a video stream. There are many "pixel clocks" in between hsync pulses. How can I get a pulse or signal exactly at the midpoint between two hsync pulses? Basically I want to be able to find the horizontal center of the screen. Here is what I have:
reg [30:0] count;
reg [30:0] counter;
wire left;
always #(posedge pixclk)
begin
if (hsync == 1'b1)
begin
count = counter;
counter = 1'b0;
end
else
begin
counter = counter + 1;
end
end
assign left = (counter < (count / 2) ? 1'b1 : 1'b0);
First, I don't know if this is conceptually the right way to do this.
Second, if hsync is held low for more than one pixclk cycle, then count will always be zero. It will only work if the width of hsync pulse is exactly one clock cycle or less.
First: You should use non-blocking assignments in a clocked section. <=
In your case you tell me that you have an hsync which is longer then your pixel clock.
One way is to count pulses when the hsync is low and store the result when it is high. That would require a small two-state Fine-State-Machine (FSM)
However I personally find making Fine-State-Machines a burden to be avoided. So here is what I would do:
Detect the edge of the hysnc (when it goes high or when it goes low) and count between the edges. Here is the core of the code:
reg hsync_one_cycle_delayed;
always #(posedge pixclk)
begin
hsync_one_cycle_delayed <= hsync;
if (hsync==1'b1 && hsync_one_cycle_delayed==1'b0)
// We have a detected a rising edge on hsync
begin
count <= counter;
counter <= 31'h0;
end
else
counter <= counter + 1;
end
Some final notes:
It assume the hsync is synchronous to the pixel clock.
This code has no reset which seems to become the norm in FPGA code, but which I personally deplore.
I have been giving a specification to derive 10MHz,5MHz and 1MHz from a 20MHz system clock. I am also supposed to design posedge and negedge flags for all the three derived clocks.
I used a 4 bit counter which counted from 0-15 and the counter[0] gave me the 10MHz clock signal and the counter [1] gave me the 5MHz signal. I used another 5 bit counter which counted from 0-9. I made my 1MHz signal register toggle for 0-9 each count, which gave me the 1MHz clock signal.
Now I am struggling to design the posedge and negedge flags for all three of the clocks. I used a combination logic of posedge = a^!b; but I could get the flags for 10MHz and 5MHz but couldn't extract my 1MHz flags from this method.
I was suggested to use my two counters (4 bit and 5 bit) to easily design the flags for all three of them. Kindly suggest on this
my 1MHz snippet using the 5 bit counter
if(counter_1MHz == 5'd9)
begin
counter_1MHz <= 5'd0;
clk_1MHz_reg <= ~clk_1MHz_reg;
end
else
begin
counter_1MHz <= counter_1MHz + 5'd1;
clk_1MHz_reg <= clk_1MHz_reg;
end
assign clk_1MHz = clk_1MHz_reg;
posedge = a&!b where b is one cycle delayed from a:
always #(posedge clock)
b <= a;
assign rising_edge = a & !b; // a is high but was low
Beware that a posedge from a 10 MHz clock derived from a 20MHz clock, is the 10MHz clock again. The negedge is the inverse clock. As such the requirement for those signals seems not very much thought out.
Building on your code:
reg clk_1MHz_delay;
wire clk_1MHz_rising;
always#(posedge clk_20MHz)
clk_1MHz_delay <= clk_1MHz;
assign clk_1MHz_rising = clk_1MHz & !clk_1MHz_delay;
I'm attempting to control an TC8020 mosfet (http://ww1.microchip.com/downloads/en/DeviceDoc/tc8020.pdf) through a md1715 ultrasound driver (http://ww1.microchip.com/downloads/en/DeviceDoc/md1715.pdf) to eventually control ultrasound sensors.
i.e. FPGA --> MD1715 --> TC8020 --> Transmitters
From what I can tell in the md1715 truth tables (md1715.pdf page 4), I should be able to drive an output voltage by something like SEL=1, POS=1, NEG=0?
I'm trying to do something like this in my verilog code, but it's been a long time since I've used a HDL. Does something like this make sense? I'm not exactly sure how to change frequencies, etc.
module main(input ADC0CLK,
output SELA, //pin mappings set up to fpga
output POSA,
output NEGA
);
reg r_sel_a;
reg r_pos_a;
reg r_neg_a;
/*
// Hardwire for now just to test output.
// From what I can tell this should drive a constant voltage of 1?
assign SELA = 1'b1;
assign POSA = 1'b1;
assign NEGA = 0;
*/
assign SELA = r_sel_a;
assign POSA = r_pos_a;
assign NEGA = r_neg_a;
always # (posedge ADC0CLK or negedge ADC0CLK)
begin: TRANSMITA
if (ADC0CLK == 1) begin
r_sel_a <= 1'b1;
r_pos_a <= 1'b1;
r_neg_a <= 0;
end else if (ADC0CLK == 0) begin
r_sel_a <= 1'b1;
r_pos_a <= 0;
r_neg_a <= 1'b1;
end
end
endmodule
Much thanks
This code is not synthezisable. You cannot have a process (always) that works on both edges of clock. I see two options here:
You can use 2x faster clock and then your process will work only on posedge of this faster clock.
You can use ODDR primitve. ODDR is a xilinx primitive to drive data on two clock edges, here you can find description of xilinx 7-series IO resources. if you are using FPGA from other vendors then you have to search for such primitive, I found that altera has ALTDDIO_OUT ipcore but I've never used it.
Imo option 2 is better, you shouldn't have timing problems which can occure in first option.