Do you recognize the letters in the example image above? If you do, I suppose you’re a Hebrew speaker. And since the letters are shown in handwriting style, just a Hebrew keyboard is not enough, since the keys are marked with type-style letters. With basic Hebrew skills, the translation is obvious. Others will have to work harder.
This Captcha generator is intended to filter non-Hebrew speakers from Hebrew sites. Antisemitic forum spam is a well-known problem. While capthcas based upon digits solve the problem Israeli children face with English letters, a Hebrew letters captcha allow the Israelis in, and keep those who have nothing to do there anyway, out.
The software, which is released under LGPL (font under GPL) is a PHP script, which should run out of the box on any fairly updated web server.
Encoding issues (important!)
Your page must be encoded in either UTF-8, windows-1255 or ISO 8859-8. Otherwise, the user may enter the right code but will be denied access anyhow, because the browser messed up the Hebrew letters when submitting the form (and the code typed). It may work with other encodings, but it’s not recommended to gamble with this.
The good news are, that your page is most likely already encoded in one of these. The bad news are that you have to make sure that the browser doesn’t get confused.
Keep in mind, that unless the encoding is explicitly declared in HTML or by the HTTP headers, the browser will pick its own default, which depends on, well, everything. So if you don’t declare the encoding, the captcha will work for some and not for others, with no apparent explanation.
It’s common to declare the encoding with one of the following lines in the HTML code. Pick the one that doesn’t mess your page up. One of these lines should be between your <head> and </head> tags.
Hebrew has two special issues: It goes from right to left, and we have the special treatment of the last letter. To avoid problems, it’s recommended to tell users
to copy the letters from right to left (which the natural behavior)
not to alter the last letter (e.g. Mem to Mem-Sofit)
Please visit the the original site and read their documentation before attempting to install the Hebrew version. Both versions are virtually the same.
And if you have problems installing the Hebrew, please make sure that you manage to do it with the original version first.
The font used by default is “Ktav Yad” (which means “handwriting” in Hebrew) by Maxim Iorsh. Any TrueType font supporting hebrew will do, but you can download other free fonts at Culmus’ web site at SourceForge.
Having made several FPGA projects for my clients, I’ve learned that most of them are reluctant to use the Xilinx FPGA Editor. While most seem to realize that’s it’s a valuable tool, few really grasp the enormous advantage it offers, in particular when debugging FPGA designs: The possibilities to view the FPGA down to the level of the basic logic elements, as well as making small, yet arbitrary changes, without needing to go through place and route again. This opens for several techniques, which make a huge difference in the frustration of debugging, not to mention time.
Maybe because the documentation is currently somewhat laconic (anyone seen a good user’s reference manual?) most people skip this tool.
The video tutorial presented below should make you friends with the tool. It doesn’t cover nearly all functionality, but focuses on the things you need to get started, and also do a few useful things. It’s a private initiative, so Xilinx are of course not responsible for anything said in it. It was shot in December 2007, showing the tools of ISE 9.2.
Published on Youtube, the tutorial is given in three parts:
How to watch any signal within your FPGA design with a regular oscilloscope, almost as easy as in the pre-FPGA times, when all signals were physically exposed on the board.
Topics covered:
Opening a second List window
Finding the output pin to sacrifice for debugging
Disconnecting the output pin from its previous connection
Connecting the new net with the “Route” button
Routing the net to the IOB with the “Autoroute” button
A few words about skews
Briefly: About the “Probes” utility
Virtex-4 (and newer devices): A possible routing problem
Posted Under: FPGA
This post was written by eli on January 1, 2009 Comments (0)
I love LaTeX. It’s my preferred tool whenever I need to write a document in English. But it had one little problem: The documents it generated, even though beautifully typeset, had an academic look. For someone who submits the documents to hitec companies, an engineering-like look was more appealing.
So I wrote my own document style. It’s inspired from several technical documents, such as application notes and manuals which are published by large companies in the industry.
After downloading (and possibly updating TeX’s search cache), just change the well-known \documentclass{article} to \documentclass{hitec} and enjoy the new look.
Here’s a problem I encounter in several fields: Find the local maxima and minima in some noisy signal, which typically looks like the following graph:
The local maxima and minima are plotted as red and green stars on the graph. To the eye it’s so obvious where they are, but making a computer find them can turn out tricky.
Let’s start with what not to do: Using the well-known zero-derivate method. Due to the noise, which is always there in real-life signals, accidental zero-crossings of the first derivate occur, yielding false detections. The typical solution is to smooth the curve with some low-pass filter, usually killing the original signal at the same time. The result is usually that the algorithm goes horribly wrong where it’s so obvious to the eye.
In many cases, we don’t really care about maxima and minima in the mathematical sense. We can see the peaks and valleys, and we want the computer to find them. This is what “peakdet” does.
The trick here is to realize, that a peak is the highest point betweem “valleys”. What makes a peak is the fact that there are lower points around it. This strategy is adopted by “peakdet”: Look for the highest point, around which there are points lower by X on both sides.
Let’s see an example: First, let’s create the graph shown in the figure above:
Now we’ll find the peaks and valleys: (you’ll need to copy the “peakdet” function from the bottom of this page and put it in your working directory or a directory in the MATLAB search path):
Note the call to peakdet(): The first argument is the vector to examine, and the second is the peak threshold: We require a difference of at least 0.5 between a peak and its surrounding in order to declare it as a peak. Same goes with valleys.
The returned vectors “maxtab” and “mintab” contain the peak and valley points, as evident by their plots (note the colors).
The vector’s X-axis values can be passed as a third argument (thanks to Sven Billiet for his contribution on this), in which case peakdet() returns these values instead of indices, as shown in the following example:
And from here we continue like before, but note that the X axis represents “t” and not indices.
>> hold on; plot(mintab(:,1), mintab(:,2), 'g*');
>> plot(maxtab(:,1), maxtab(:,2), 'r*');
As for the implementation of this function: The work is done with a for-loop, which is considered lousy practice in MATLAB. Since I’ve never needed this function for anything else than pretty short vectors (< 100000 points), I also never bothered to try speeding it up. Compiling to MEX is a direct solution. I’m not sure if it’s possible to vectorize this algorithm in MATLAB. I’ll be glad to hear suggestions.
A final note: If you happen to prefer Python, you could try this (someone has been kind enough to convert this function). There are also a version in C by Hong Xu and a version in FORTRAN 90 by Brian McNoldy. I haven’t verified any of these.
And here is the function. Copy and save it as ‘peakdet.m’. It’s released to the public domain:
function[maxtab, mintab]=peakdet(v, delta, x)%PEAKDET Detect peaks in a vector% [MAXTAB, MINTAB] = PEAKDET(V, DELTA) finds the local% maxima and minima ("peaks") in the vector V.% MAXTAB and MINTAB consists of two columns. Column 1% contains indices in V, and column 2 the found values.% % With [MAXTAB, MINTAB] = PEAKDET(V, DELTA, X) the indices% in MAXTAB and MINTAB are replaced with the corresponding% X-values.%% A point is considered a maximum peak if it has the maximal% value, and was preceded (to the left) by a value lower by% DELTA.% Eli Billauer, 3.4.05% This function is released to the public domain; Any use is allowed.
maxtab = [];
mintab = [];
v = v(:); % Just in case this wasn't a proper vectorif nargin < 3
x = (1:length(v))';
else
x = x(:);
iflength(v)~= length(x)
error('Input vectors v and x must have same length');
endendif (length(delta(:)))>1
error('Input argument DELTA must be a scalar');
endif delta <= 0
error('Input argument DELTA must be positive');
end
mn = Inf; mx = -Inf;
mnpos = NaN; mxpos = NaN;
lookformax = 1;
fori=1:length(v)
this = v(i);
if this > mx, mx = this; mxpos = x(i); endif this < mn, mn = this; mnpos = x(i); endif lookformax
if this < mx-delta
maxtab = [maxtab ; mxpos mx];
mn = this; mnpos = x(i);
lookformax = 0;
endelseif this > mn+delta
mintab = [mintab ; mnpos mn];
mx = this; mxpos = x(i);
lookformax = 1;
endendend
I’m using MATLAB since about 1992. One of the things that I’ve always missed, as a communication engineer, is a quick and dirty spectrum plot of signals. I want to see what the spectrum analyzer will show me when I’ll run the signal through it, and not some analytic plot, which looks nothing like.
The “easyspec” MATLAB function does exactly that. Using this function on a time signal has the feel of plugging in a spectrum analyzer: You get some simple, concise image (scaled in dBs, for us engineers), which is as reliable as if you measured the signal. Meaning, that if the signal is not stationary (choose whatever sense you want for “stationary”) you may want to re-run the function to see if you get the same result.
Let’s try a simple session (you’ll need to copy the “easyspec” function from the bottom of this page and put it in your working directory or a directory in the MATLAB search path):
This shows the spectrum of two tones, one at 440Hz, and another at 1000Hz, sampled at 44.1 kHz. Note that since we hand over the sample rate to easyspec, it will show the real-life frequency on the x axis.
The special thing about this function, is that it chooses the FFT segments at random. As a result, subsequent calls to this function on the same signal will result in slightly differently plots. This is exactly what we expect from a real-life spectrum analyzer.
As given below, this function picks (at random) 100 segments of 4096 samples, applies a Hanning window to each, and pads the vector to a length of 16384. The absolute value of the FFT of this vector is calculated.
What is displayed is the average of these 100 absolute value vectors, normalized so that a sine wave of amplitude 1 will show as approximately 0 dB on the spectrum plot. This is in the spirit of the “video average” function of common spectrum analyzers, but it works differently (spectrum analyzers usually average on the dB values). Anyhow, this makes a smoother display of truly random signals (such as noise).
The most common question I get is where the 17.127 constant came from. The honest answer is that I simply played with the number until I got 0 dB for a unity sine wave. It’s true that I could have made some calculations to reach a constant with theory behind, but I found it pretty pointless, since the accuracy is compromised anyhow. (The main reason is that the reading depends on the frequency, as each FFT bin’s response to a pure sine wave is the Hanning window’s Fourier transform).
The reason for picking the segments at random comes from real-life spectrum analyzers: Almost always, there is no synchronization between the sweep instances and the measured signal. Also, let’s keep in mind that the term “spectrum” comes from the world of probability theory, and it’s the Fourier Transform of the autocorrelation function of a side-sense stationary random signal. Now we may ask ourselves what meaning there is to a spectrum of a deterministic signal. What’s random about a plain sine wave that we apply to a spectrum analyzer?
The answer is that the time segment, on which we measure the signal, is random. If it’s not, as in MATLAB’s native “spectrum” function, a misleading result may be displayed as a result of some relation between the measured signal’s periodicity and the jumps between the FFT segments. This doesn’t happen when the signal is simple noise, but as soon as there is anything periodic about it, strange things can happen.
And finally, here is the function in question. Copy and save it as ‘easyspec.m’. It’s released to the public domain:
function[s,f]=easyspec(x,fs)%EASYSPEC Easy plot of spectrum estimate% S=EASYSPEC(X) will return a spectrum vector of% X. [S,F]=EASYSPEC(X,FS) will also return a freuqency% axis in F, while the sample frequency is given in FS.% EASYSPEC(X) and EASYSPEC(X,FS), will plot the spectrum% and return the S vector in MATLAB's "ans".% Notes:% 1. Spectrum values are in dB.% 2. The frequency domain goes from DC to the Nyquist % frequency. The "mirror part" of the spectrum is% omitted.% 3. The sample segments, from which the spectrum is% calculated are picked by random. The function might% return significantly different results each time it's% called to if X isn't stationary.% 4. EASYSPEC uses a hanning window and zero-pads by a% factor of 4. The spectrum vector will look smooth.% Eli Billauer, 17.1.01% This function is released to the public domain; Any use is allowed.if nargin==0
error('No input vector given');
endif (nargin==1)
fs=2;
end
NFFT=16384; NWIN=NFFT/4;
LOOP=100;
win=hanning(NWIN)';
x=x(:)'*(17.127/NFFT/sqrt(LOOP));
n=length(x);
maxshift=n-NWIN;
if (n<2*NWIN)
error(['Input vector should be at least of length '...
num2str(2*NWIN)]);
end
s=zeros(1,NFFT);
fori=1:LOOP
zuz=floor(rand*maxshift);
s=s+abs(fft([win.*x(1+zuz:NWIN+zuz) zeros(1,NFFT-NWIN)])).^2;
end
s=10*log10(s(1:NFFT/2));
f=linspace(0,fs/2,NFFT/2);
if nargout==0hold off;
plot(f,s);
ylabel('Power Spectrum [dB]');
xlabel('Frequency');
grid on; zoom on;
end
2022 update: This is probably quite pointless today, but that’s not reason enough to delete this post.
cdepend is a cross-reference utility, whose main purpose is mapping which function calls which in a C language project.
As projects grow and develop, it becomes harder and harder to keep track of which functions are actually used. Unused functions may exist in the project without anyone noticing.
Sometimes we want to change a function, but we’re not sure how this change will affect the entire project.
Another feature of cdepend is getting details about where library functions are called. This is important when porting a project to a non-UNIX environment, where the most basic library functions may be absent.
cdepend addresses these issues. A simple example of how it’s used and the output it generates is given below.
Project status
The project works well on my own computer. If you’re running a recent i386-Linux distro, you have good chances of having it up quickly as well. If not, you may run into trouble. If you do, I will most probably help you, assuming that you’ll supply me with sufficient information. Especially if you’re running on a recent version of Linux.
Download & Install
First you’d like to download the tarball (or get it at SourceForge). Then you do something like:
[eli@localhost cdepend]$ tar -xzf cdepend-0.02.tar.gz
[eli@localhost cdepend]$ cd cdepend-0.02
[eli@localhost cdepend-0.02]$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for cdepend
[eli@localhost cdepend-0.02]$ make
(... snipped ...)
[eli@localhost cdepend-0.02]$ su
[root@localhost cdepend-0.02]# make install
[eli@localhost cdepend-0.02]$ man cdepend
Note that there is a man page. Read it!
Example of use
Suppose that we have two files, mainfile.c and funcfile.c.
mainfile.c goes as follows:
voidf1(int);
intmain() {
f1(3);
}
and funcfile.c:
voidf2(int);
voidf1(int num) {
if (num > 0)
f2(num);
}
voidf2(int num) {
printf("Hello World %d\n", num);
f1(num-1);
}
What these functions do is really not interesting. Just for reference, here’s how we would probably compile this “project”:
First, we have to partially compile the files: We want assembly code, not object files. So we add the -S flag. We also must have the -gstabs+ flag, so debugging information is written to the assembly files. Then we run cdepend, giving it both assembly files (*.S) as input data:
The report.txt is not interesting in this case, because all functions are used and declared. It’s basically empty.
But cdepend generated a directory, funcdir at our request. Let’s see what we have in the file funcdir/f1 (generated by cdepend, of course):
Variable's name: f1()
Declared at /home/eli/example/funcfile.c:3
Varible/function is recursive (indirectly)
Functions/Variables used directly:
==================================
f2() at line(s): 5
Functions/Variables using directly:
===================================
f2() at /home/eli/example/funcfile.c:10
main() at /home/eli/example/mainfile.c:4
From this file we can learn where the function is declared, and that there is a recursive connection from f1() back to itself. Then we see that f1() is calls f2() at line 5, and that f1() is called by f2() and main().
There are similar files for f2() and main(). But we shall have a look on funcdir/printf:
Variable's name: (printf)
Found in linkable library /lib/i686/libc.so.6
Functions/Variables using directly:
===================================
f2() at /home/eli/example/funcfile.c:9
This information is important when porting a project to an environment where there is no printf. Here we can tell who uses this function.
Note that on some platforms library functions will be displayed as undeclared. This behaviour does not impact the reliabilty of the rest of the information.
And once again: There is a UNIX manual page for cdepend. man cdepend should work after installation.
Posted Under: Linux
This post was written by eli on January 1, 2009 Comments (0)
Frandom is a Linux kernel random number generator, which is 10-50 times faster than what you get from Linux’ built-in /dev/urandom. And it uses very little (/dev/frandom) or none (/dev/erandom) of the kernel’s entropy pool, so it is very useful for applications that require a handy source for lots of random data.
Its most common use seems to be wiping large hard disks with random data before encryption. It’s currently supporting 2.6 kernels, but was originally written for version 2.2.
And here’s some answers to things you might ask yourself:
Isn’t /dev/urandom enough?
Discussions about the necessity of a faster kernel random number generator rise and fall since 1996 (that I know of). My opinion is that /dev/frandom is as necessary as /dev/zero, which merely creates a stream of zeroes. The common opposite opinion usually says: Do it in user space.
What’s the difference between /dev/frandom and /dev/erandom?
In the beginning I wrote /dev/frandom. Then it turned out that one of the advantages of this suite is that it saves kernel entropy. But /dev/frandom consumes 256 bytes of kernel random data (which may, in turn, eat some entropy) every time a device file is opened, in order to seed the random generator. So I made /dev/erandom, which uses an internal random generator for seeding. The “F” in frandom stands for “fast”, and “E” for “economic”: /dev/erandom uses no kernel entropy at all.
How fast is it?
Depends on your computer and kernel version. Tests consistently show 10-50 times faster than /dev/urandom.
Will it work on my kernel?
It most probably will, if it’s > 2.6.
Is it stable?
Since releasing the initial version in fall 2003, at least 100 people have tried it (probably many more) on i686 and x86_64 systems alike. Successful test reports have arrived, and zero complaints. So yes, it’s very stable. As for randomness, there haven’t been any complaints either.
How is random data generated?
frandom is based on the RC4 encryption algorithm, which is considered secure, and is used by several applications, including SSL. Let’s start with how RC4 works: It takes a key, and generates a stream of pseudo-random bytes. The actual encryption is a XOR operation between this stream of bytes and the cleartext data stream.
Now to frandom: Every time /dev/frandom is opened, a distinct pseudo-random stream is initialized by using a 2048-bit key, which is picked by doing something equivalent to reading the key from /dev/urandom. The pseudo-random stream is what you read from /dev/frandom.
frandom is merely RC4 with a random key, just without the XOR in the end.
Does frandom generate good random numbers?
Due to its origins, the random numbers can’t be too bad. If they were, RC4 wouldn’t be worth anything.
As for testing: Data directly “copied” from /dev/frandom was tested with the “Diehard” battery of tests, developed by George Marsaglia. All tests passed, which is considered to be a good indication.
Can frandom be used to create one-time pads (cryptology)?
frandom was never intended for crypto purposes, nor was any special thought given to attacks. But there is very little room for attacking the module, and since the module is based upon RC4, we have the following fact: Using data from /dev/frandom as a one-time pad is equivalent to using the RC4 algorithm with a 2048-bit key, read from /dev/urandom.
Bottom line: It’s probably OK to use frandom for crypto purposes. But don’t. It wasn’t the intention.
Eobj is a Perl programming environment. Well, technically speaking, it’s a Perl module. Eobj stands for Easy Objects.
Idea: Object oriented programming is supported very well in Perl, but it requires some rather advanced programming techniques: Perl modules and namespaces, references, blessings and some syntactic sugars. In addition, the awareness of some special variables is required.
Eobj is intended to bring object oriented programming to the layman Perl programmer’s doorstep. “Object oriented for dummies”, if you like. It supports an easy way to create classes, and a comfortable to handle object’s properties (a.k.a. member variables). The code looks clean, and is easy to understand, even if you’re not so good in Perl.
Most of the criticism I’ve gotten regarding Eobj is that I’ve done things differently from Java and C++. That only makes me feel better. Others claim that Eobj is not needed. Those who say that usually know more than ten ways to access a referenced hash. Most Perl programmers don’t want to know what a reference is. And I understand them.
For someone who understands the basic principles of object oriented programming and “normal” Perl script programming, it should take no longer than 15 minutes before being able to get started. There are a few quite simple rules to follow, and off you are.
Almost all features of “classic” Perl OO programming is supported. The main cost of using Eobj is some overhead. But if you’re worried about memory and speed, why are you using Perl?
Eobj is derived from the Perlilog project. In fact, Perlilog’s object environment is very similar to Eobj’s, there are minor differences. Eobj is intended as a general-purpose environment, while Perlilog’s object environment is adapted to its certain purpose.
Somewhere in 2006 TI (Texas Instruments) released a clock synthesizer, CDCE906, which is pretty much everything one can look for in a system clock generator: Several (up to 6) clock outputs derived from a single reference clock or crystal with excellent multiplication and division capabilities, not to mention low jitter, slew rate control, spread spectrum and more. On top of all, it’s surprisingly low-priced. So it’s a chip you want to consider, even if all you (think you) need for now, is one single system clock with a fixed frequency. It will save you, when you’ll discover three weeks before release that you actually need another clock with a weird frequency. Believe me.
Except for the non-E devices, (that is, CDC906 and CDC706, which TI seems to neglect) the devices’ setting can be preprogrammed into an on-chip EEPROM, before or after the chip is put on the PCB board. If this is enough for you, frankly, you have nothing to look for on this page. On the other hand, if you want to set the current configuration regardless of the EEPROM, it’s possible over the SMBus.
Now, SMBus is more or less like I2C (also known as IIC), so if you have a controller on the board with I2C/SMBus cababilities, you may want to use it (if it has I2C, I suggest knowing the differences). If there is no controller around, or you prefer the FPGA to set up the synthesizer, the Verilog code below is what you need.
It should be pointed out, that TI also have another very similar device, CDCE706, which is surprisingly enough more capable than its “little brother” CDCE906. Their register structure is identical however, so the code below can be used for CDCE706 as well.
The only downside about both devices is that being very versatile, they’re also complicated. I’m not going to describe how to run these chips. There is no way out of reading the extensive datasheet, and I promise finding some hidden treasures there. The only thing this module will do for you, is get the right values to the right register.
So let’s get to business. Before doing anything else, be sure to set the parameter “clk_freq” to the frequency of the module’s input clock “clk” (in MHz, nearest integer). This is crucial, because the SMBus is derived from this clock. If several frequencies are possible, make “clk_freq” the highest one.
Important notes:
Pullup resistors for sclk and sdata are mandatory. Nothing will work without them. When tied to a 3.3V supply, they should be between 10 kOhm and 33 kOhm.
This module acts as an SMBus master. It must therefore not share the sclk and sdata lines with another master, unless it’s assured that they won’t attempt to take control at the same time. The simplest solution is to make one-on-one connections of sclk and sdata between the chip and the FPGA (don’t forget the pullups!).
Verify that the FPGA outputs are indeed 3.3V (this is usually something you should set). Modern FPGA’s take a lower voltage by default.
Now the basic I/O’s:
clk
Input clock, which drives the module’s logic and from which the SMBus clock is derived. Preferably with a known and stable frequency. The module is sensitive to this clock’s rising edge only.
reset
Asynchronous reset, active high (input). May be tied to ’0′ if the state variable “state” can be assured to wake up as “st_idle” (don’t trust the syntheizer to do this implicitly)
send_data
Input, synchronous with “clk”: Start send data to chip command. Set to ’1′ to update all registers of the chip. This line should be ’1′ for at least one “clk” cycle, but not more than the time it takes for the full write to complete.
busy
Output, synchronous with “clk”: This line is high as long as the register data is being written to the chip over the SMBus.
error
Output, synchronous with “clk”: This line goes high if an acknowledgement from the chip is missing, which indicates some kind of error. The line remains high until the next initiation with “send_data”.
sclk
Output: To be directly connected to the chip’s pin #10 (SCLOCK). This pin toggles between ’0′ and high-Z. Do verify that your development tools indeed create a high-Z condition on the output when the ‘z’ value is assigned to this line (Xilinx FPGA tools are OK with this). Don’t forget the pullup resistor
sdata
Output: To be directly connected to the chip’s pin #9 (SDATA). This pin toggles between ’0′ and high-Z. Do verify that your development tools indeed create a high-Z condition on the output when the ‘z’ value is assigned to this line. Don’t forget the pullup resistor
S0
Output: To be directly connected to the chip’s pin #1 (S0/A0/CLK_SEL). Will be tied to constant ’1′ (see datasheet for meaning).
S1
Output: To be directly connected to the chip’s pin #2 (S1/A1). Will be tied to constant ’1′ (see datasheet for meaning).
Next we have the actual synthesizer parameters, whose meaning should be obvious to whoever has read the datasheet well. The only thing note is that the term “PLL” has been exchanged for “VCO”, which I find more intuitive. So VCO1_M and VCO1_N are the M and N for PLL1, using the datasheet’s terminology, etc. The comments in the module itself may help as well.
All these inputs can be constants (which will shrink the synthesized logic) or you can wire them to whatever you like, but these inputs must be steady as long as their content is flushed to the chip ( = as long as the “busy” output is high).
So all we have left is the module itself. I’ve lifted the copyright restrictions for it, so you can use it in any way you like.
(And by the way: I have no special relations with TI whatsoever. Not even as a freelancer).
———————————–
// Eli Billauer, 30.12.06// This function is released to the public domain; Any use is allowed.module cdce906
(
clk, reset, send_data,
busy, error,
sclk, sdata, S0, S1,
VCO1_M, VCO1_N, VCO1_bypass, VCO1_hi_freq_range,
VCO2_M, VCO2_N, VCO2_bypass, VCO2_hi_freq_range,
VCO3_M, VCO3_N, VCO3_bypass, VCO3_hi_freq_range,
P0_VCO_select, P0_div, P1_VCO_select, P1_div,
P2_VCO_select, P2_div, P3_VCO_select, P3_div,
P4_VCO_select, P4_div, P5_VCO_select, P5_div,
Y0_en, Y0_inv, Y0_slew_rate, Y0_div_select,
Y1_en, Y1_inv, Y1_slew_rate, Y1_div_select,
Y2_en, Y2_inv, Y2_slew_rate, Y2_div_select,
Y3_en, Y3_inv, Y3_slew_rate, Y3_div_select,
Y4_en, Y4_inv, Y4_slew_rate, Y4_div_select,
Y5_en, Y5_inv, Y5_slew_rate, Y5_div_select,
SSC_mod_select, SSC_freq_select
);
input clk;
input reset; // Active highoutput sclk;
inout sdata;
output S0, S1;
output busy, error;
input send_data;
// PLL settings:input [8:0] VCO1_M;
input [11:0] VCO1_N;
input VCO1_bypass; // '1' means VCO bypassedinput VCO1_hi_freq_range; // '1' means 180-300 MHzinput [8:0] VCO2_M;
input [11:0] VCO2_N;
input VCO2_bypass; // '1' means VCO bypassedinput VCO2_hi_freq_range; // '1' means 180-300 MHzinput [8:0] VCO3_M;
input [11:0] VCO3_N;
input VCO3_bypass; // '1' means VCO bypassedinput VCO3_hi_freq_range; // '1' means 180-300 MHz// Post divider (P) settings// For Px_VCO_select:// 0 = input clock (bypass)// 1 = VCO1// 2 = VCO2// 3 = VCO2 with spread spectrum modulation// 4 = VCO3input [2:0] P0_VCO_select;
input [6:0] P0_div;
input [2:0] P1_VCO_select;
input [6:0] P1_div;
input [2:0] P2_VCO_select;
input [6:0] P2_div;
input [2:0] P3_VCO_select;
input [6:0] P3_div;
input [2:0] P4_VCO_select;
input [6:0] P4_div;
input [2:0] P5_VCO_select;
input [6:0] P5_div;
// Output (Y) settingsinput Y0_en; // '1' is output enabledinput Y0_inv; // '1' means invertedinput [1:0] Y0_slew_rate; // '11' is nominalinput [2:0] Y0_div_select; // 0=P0, 1=P1, ... , 5=P5 input Y1_en; // '1' is output enabledinput Y1_inv; // '1' means invertedinput [1:0] Y1_slew_rate; // '11' is nominalinput [2:0] Y1_div_select; // 0=P0, 1=P1, ... , 5=P5 input Y2_en; // '1' is output enabledinput Y2_inv; // '1' means invertedinput [1:0] Y2_slew_rate; // '11' is nominalinput [2:0] Y2_div_select; // 0=P0, 1=P1, ... , 5=P5 input Y3_en; // '1' is output enabledinput Y3_inv; // '1' means invertedinput [1:0] Y3_slew_rate; // '11' is nominalinput [2:0] Y3_div_select; // 0=P0, 1=P1, ... , 5=P5 input Y4_en; // '1' is output enabledinput Y4_inv; // '1' means invertedinput [1:0] Y4_slew_rate; // '11' is nominalinput [2:0] Y4_div_select; // 0=P0, 1=P1, ... , 5=P5 input Y5_en; // '1' is output enabledinput Y5_inv; // '1' means invertedinput [1:0] Y5_slew_rate; // '11' is nominalinput [2:0] Y5_div_select; // 0=P0, 1=P1, ... , 5=P5 // Spread spectrum settingsinput [2:0] SSC_mod_select; // See datasheetinput [3:0] SSC_freq_select; // See datasheetreg SMBus_en, pre_en;
reg kickoff;
reg [2:0] state;
reg get_bit;
reg next_bit, this_is_ack, wait_for_ack;
reg sdata_d;
reg error;
reg [4:0] word_addr;
reg [3:0] bit_pos;
reg no_more_bits;
reg [7:0] SMBus_word;
reg [11:0] div_counter;
reg sclk_logic, sdata_logic;
parameter clk_freq = 10; // In MHz, nearest integerparameter st_idle = 0,
st_start0 = 1,
st_start1 = 2,
st_bit0 = 3,
st_bit1 = 4,
st_bit2 = 5,
st_stop0 = 6,
st_stop1 = 7;
// Emulated open collector output// Note that sclk and sdata must be pulled up, possibly with// a PULLUP constraint on the IOB (or a 10 kOhm ext. resistor)assign sclk = sclk_logic ? 1'bz : 1'b0 ;
assign sdata = sdata_logic ? 1'bz : 1'b0 ;
assign S0 = 1; // No powerdownassign S1 = 1; // No output inhibit// SMBus_en should be high every 10 us// This allows a huge multicycle path constraint on SBBus_en,// but "kickoff" MUST BE EXCLUDED from the group.always @(posedge clk)
begin
SMBus_en <= pre_en;
sdata_d <= sdata;
if (div_counter == ((clk_freq * 10) - 1))
begin
div_counter <= 0;
pre_en <= 1;
endelsebegin
div_counter <= div_counter + 1;
pre_en <= 0;
endendalways @(posedge clk orposedge reset)
if (reset)
kickoff <= 0;
elseif (send_data)
kickoff <= 1;
elseif (SMBus_en)
kickoff <= 0;
assign busy = kickoff || (state != st_idle);
always @(posedge clk orposedge reset)
if (reset)
begin
state <= st_idle;
error <= 0;
endelseif (SMBus_en)
case (state)
st_idle: begin
sclk_logic <= 1;
sdata_logic <= 1;
get_bit <= 0;
if (kickoff)
state <= st_start0;
end
st_start0: begin
sclk_logic <= 1;
sdata_logic <= 0;
state <= st_start1;
error <= 0;
end
st_start1: begin
sclk_logic <= 0;
state <= st_bit0;
end
st_bit0: begin
sclk_logic <= 0;
sdata_logic <= next_bit;
wait_for_ack <= this_is_ack;
get_bit <= 1;
state <= st_bit1;
end
st_bit1: begin
sclk_logic <= 1;
get_bit <= 0;
state <= st_bit2;
end
st_bit2: begin
sclk_logic <= 0;
if (wait_for_ack && !sdata_d && !kickoff)
state <= st_bit2;
elseif (no_more_bits)
state <= st_stop0;
else
state <= st_bit0;
if (wait_for_ack && sdata_d && sclk_logic) // No acknowledge
error <= 1;
end
st_stop0: begin
sclk_logic <= 0;
sdata_logic <= 0;
state <= st_stop1;
end
st_stop1: begin
sclk_logic <= 1;
state <= st_idle;
endendcasealways @(posedge clk)
if (SMBus_en)
beginif (kickoff)
begin
word_addr <= 0;
bit_pos <= 7;
no_more_bits <= 0;
endelseif (get_bit)
begin
bit_pos <= (bit_pos == 0) ? 8 : bit_pos - 1;
if (bit_pos == 0)
word_addr <= word_addr + 1;
if ((word_addr == 29) &&
(bit_pos == 8))
no_more_bits <= 1;
endif (bit_pos == 8) // Ack positionbegin
next_bit <= 1; // Don't pull bus to zero
this_is_ack <= 1;
endelsebegin
next_bit <= SMBus_word[ bit_pos[2:0] ];
this_is_ack <= 0;
endendalways @(posedge clk)
if (SMBus_en)
case (word_addr)
0: SMBus_word <= 8'b1101001_0 ; // Slave address, write1: SMBus_word <= 0 ; // Command code = Block (write)2: SMBus_word <= 26 ; // Byte count3: SMBus_word <= 0 ; // Byte 04: SMBus_word <= VCO1_M[7:0] ;
5: SMBus_word <= VCO1_N[7:0] ;
6: SMBus_word <= { VCO1_bypass, VCO2_bypass, VCO3_bypass, VCO1_N[11:8], VCO1_M[8] } ;
7: SMBus_word <= VCO2_M[7:0] ;
8: SMBus_word <= VCO2_N[7:0] ;
9: SMBus_word <= { VCO1_hi_freq_range, VCO2_hi_freq_range,
VCO3_hi_freq_range, VCO2_N[11:8], VCO2_M[8] } ;
10: SMBus_word <= VCO3_M[7:0] ;
11: SMBus_word <= VCO3_N[7:0] ;
12: SMBus_word <= { P0_VCO_select, VCO3_N[11:8], VCO3_M[8] } ;
13: SMBus_word <= { P1_VCO_select, 1'b0, 2'b00, 2'b00 } ;
14: SMBus_word <= { 2'b00, P3_VCO_select, P2_VCO_select } ;
15: SMBus_word <= { 2'b00, P5_VCO_select, P4_VCO_select } ;
16: SMBus_word <= { 1'b0, P0_div } ;
17: SMBus_word <= { 1'b0, P1_div } ;
18: SMBus_word <= { 1'b0, P2_div } ;
19: SMBus_word <= { 1'b0, P3_div } ;
20: SMBus_word <= { 1'b0, P4_div } ;
21: SMBus_word <= { 1'b0, P5_div } ;
22: SMBus_word <= { 1'b0, Y0_inv, Y0_slew_rate, Y0_en, Y0_div_select } ;
23: SMBus_word <= { 1'b0, Y1_inv, Y1_slew_rate, Y1_en, Y1_div_select } ;
24: SMBus_word <= { 1'b0, Y2_inv, Y2_slew_rate, Y2_en, Y2_div_select } ;
25: SMBus_word <= { 1'b0, Y3_inv, Y3_slew_rate, Y3_en, Y3_div_select } ;
26: SMBus_word <= { 1'b0, Y4_inv, Y4_slew_rate, Y4_en, Y4_div_select } ;
27: SMBus_word <= { 1'b0, Y5_inv, Y5_slew_rate, Y5_en, Y5_div_select } ;
28: SMBus_word <= { 1'b0, SSC_mod_select, SSC_freq_select } ; // Byte 25default: SMBus_word <= 0 ;
endcaseendmodule
Posted Under: FPGA
This post was written by eli on January 1, 2009 Comments (0)
Perlilog is a command-line tool which generates Verilog modules from a set of files, which come in several other formats. It was originally designed to integrate Verilog IP cores. It’s released as free software (GPL).
Motivation: Anyone who has needed to integrate a few Verilog modules into something working, knows it’s a headache. It’s not only a mechanic task, but also a source of bugs. Since Verilog modules’ interface is basically wires, the integration task requires an accurate understanding of what each wire stands for, and how it’s expected to behave. Having many details to keep track on, it’s common that undesidered
Perlilog’s main concept is that handling IP cores (and Verilog modules in general) should be intuitive. We think about IP cores as black boxes, so we should also relate to them as black boxes when connecting them. When connecting cores, we imagine that as drawing a thick line between them. So should the connection be done, when actually integrating the system.
Perlilog introduces an alternative concepts for connecting between cores. The main issues are:
Rather than connecting wires (Verilog inputs and outputs), connect ports. A port is a loosely defined object, which holds one simple rule: Connecting port A with port B should mean what one would normally expect from drawing a line between two blocks in a schematic block diagram. Surprisingly enough, it’s almost always possible to properly define this meaning.
Cores should be black boxes, and they must be easy to configure. The meaning of each attribute should be obvious (as opposed to editing define files)
Perlilog is also useful for much simpler tasks, such as massive connection of Verilog module’s inputs and outputs to pads, and other tasks that are readily performed with Perl scripts. It’s a good starting point for writing a Perl script which handles Verilog code, even for the simpler tasks (and hence the project’s name, as a “mixture” between Perl and Verilog).
Most Linux distributions have Perlilog packaged, so the easiest way to obtain it is with yum, apt-get, or whatever applies. Or you may download the project and its guide or directly from this site: Perlilog-1.0.tar.gz and perlilog-guide-1.0.pdf.