-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e3fae2e
Showing
43 changed files
with
3,564 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
This is a fork of OpenVerifla that tries to do a few things: | ||
|
||
1) Document some of the settings a bit better | ||
2) Fix a bug where samples that changed on one clock were not handled properly | ||
3) Add synchronous memory that is easier for some tools to infer | ||
4) Some minor cleanups and plans for enhancments | ||
5) C tool to read output and generate VCD directly (see C directory for build instructions) | ||
6) Adds clock enable/qualifer | ||
7) Adds armed and trigger outputs | ||
|
||
The PDF attached has some good information on it. However, a few things to note: | ||
|
||
1) Do not set Run to 1 in your code unless your trigger is infrequent. If data constantly | ||
spews out of the FPGA, the JAVA code can not sync to it. | ||
|
||
2) There are some strange unsquashed bugs. For example, on the Lattice iCe40 | ||
with Icestorm tools (at least) setting memory to 256 bytes and the trigger position to | ||
128 causes a hang. Trigger positions at 127 and 129 are fine. | ||
|
||
Possible Enhancements | ||
1) Uart clock vs Sample clock (Uart clock >> Sample clock) | ||
2) Clock Enable for sample clock (done) | ||
3) Change post trigger samples to do post trigger memory words (or document to set huge #) | ||
4) Java: Pick up Verilog file from template | ||
|
||
=== Quick Start | ||
1. Link or copy the verifla directory (the one under verilog) to your project directory | ||
2. Copy config_verifla.v.template to your working directory and rename it to config_verifla.v | ||
3. Make sure your Verilog tool will look in the verifla directory as a library | ||
4. Make sure the search path for includes will look in your project directory first | ||
5. Edit config_verifla.v in your project directory to se clock speed, baud rate, memory size, etc. | ||
6. Write your verilog in the project directory. | ||
7. Create a top_of_verifla module. Here are the signals: | ||
* clk - Clock | ||
* cqual - Qualifier for data capture clock (UART and other things use clk alone). If you don't want a qualifer, just set to 1'b1. IMPORTANT: You do need to set this to something. | ||
* rst_l - Active low reset. | ||
* sys_run - High to arm logic analyzer. If you only want to arm from the PC, set to 1'b0. | ||
* data_in - Your inputs. Group together like {led3, led2, led1, led0, count[3:0]}. | ||
* uart_XMIT_dataH - Your RS232 transmit line | ||
* uart_REC_dataH - Your RS232 receive line | ||
* armed - digital output showing LA is armed | ||
* triggered - digital output showing LA is triggered | ||
8. Once running you can use the original Java program to create a .v file you will need to simulate or the C program (la2vcd) to create a .vcd you can read using a waveform viewer (like GTKWave) | ||
|
||
=== Notes about using GTKWave | ||
The C program creates a simple dump that has the entire capture data and also each byte captured. You can supress the bytes (-W) or the aggregate (-B) if you like. However, you really want to have the signals broken back out like they are in your code. | ||
|
||
Suppose you have 16-bits of data like this: | ||
counter8[7:0], led0, state[6:0] | ||
|
||
It is easy to add the capdata[15:0] data to GTKWave. Then expand it into bits. Select the | ||
counter8 bits and press Combine Down on the Edit menu (or Combine Up if you are reversed endian). | ||
This will prompt you for a name so enter "counter8" and press OK. Now you'll have a counter 8 signal. Repeat for state. For the led0 signal, you can create an alias. | ||
|
||
Of course, this is painful to set up every time so use Write Save File on the File menu. This will save the layout for next time you load a VCD with the same format. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,306 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <libserialport.h> // From SIGROK -- need newer version than Ubuntu provides :( | ||
// Look at https://sigrok.org/wiki/Libserialport | ||
#include <ctype.h> | ||
#include <unistd.h> | ||
#include <time.h> | ||
#include <stdint.h> | ||
|
||
#define USERCMD_RESET 0 | ||
#define USERCMD_RUN 1 | ||
|
||
// Need to make command line options | ||
#define BAUD 9600 | ||
#define CAPTURE 2 | ||
#define REPEAT 1 | ||
#define SIZE 256 | ||
#define COUNT (SIZE*(REPEAT+CAPTURE)) | ||
|
||
void help() | ||
{ | ||
fprintf(stderr,"Usage: la2vcd [-B] [-W] [-F frequency] [-T timescale] -b baud, -t trigger_pos -c cap_width, -r repeat_width, -n samples -o vcd_file port_name\n"); | ||
fprintf(stderr,"You need all the lower case options, although baud will default to 9600\n"); | ||
fprintf(stderr,"-B output only bytes of capture\n-W output only words (default is both bytes and words)\n"); | ||
fprintf(stderr,"-F sets frequency in MHz (e.g., -F 250).\n" | ||
"Or you can set the timescale (e.g, -T 1ns) with -T. Note the timescale should be twice the clock frequency. Default to 1nS and you do your own math.\n"); | ||
fprintf(stderr,"Al Williams [email protected]\n"); | ||
exit(1); | ||
} | ||
|
||
char *binary(uint64_t v, unsigned int bits) | ||
{ | ||
static char buffer[65]; | ||
char *p=buffer+sizeof(buffer)-1; | ||
memset(buffer,'0',sizeof(buffer)); | ||
*p--='\0'; | ||
while (v) | ||
{ | ||
*p--=(v&1)?'1':'0'; | ||
v=v>>1; | ||
} | ||
return buffer+sizeof(buffer)-1-bits; // note this is static with all that implies | ||
} | ||
|
||
|
||
|
||
uint64_t getbin(unsigned width, unsigned char *buf, unsigned base) | ||
{ | ||
uint64_t v=0; | ||
int j; | ||
for (j=0;j<width;j++) v=v*0x100+buf[base+j]; | ||
return v; | ||
} | ||
|
||
void getbline(unsigned w1, unsigned w2, char *buf, unsigned base, uint64_t *v1, uint64_t *v2 ) | ||
{ | ||
|
||
*v1=getbin(w1,buf,base+w2); | ||
*v2=getbin(w2,buf,base); | ||
} | ||
|
||
int bflag=3; // bytes=1, words=2 | ||
|
||
|
||
void writeline(FILE *f,uint64_t *t,uint64_t rpt, uint64_t data, int trigger, int capwidth) | ||
{ | ||
unsigned int i; | ||
unsigned int j; | ||
for (j=0;j<rpt;j++) | ||
{ | ||
fprintf(f,"#%lu\n1!\n",*t); // always do clock | ||
if (j==0) // only have to do the first data point for the change block | ||
{ | ||
if (bflag&2) fprintf(f,"b%s # \n", binary(data,capwidth*8)); | ||
if (bflag&1) for (i=0;i<capwidth;i++) fprintf(f,"b%s %c \n",binary(data>>(8*i)&0xFF,8),'&'+i); | ||
if (trigger) | ||
fprintf(f,"1^\n"); | ||
} | ||
fprintf(f,"#%lu\n0!\n",*t+1); // always trim up the clock | ||
|
||
*t+=2; | ||
} | ||
} | ||
|
||
|
||
void sizerr(const char *msg) | ||
{ | ||
fprintf(stderr,"Error: %s exceeds 64 bits\n",msg); | ||
exit(9); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
struct sp_port *port; | ||
int err; | ||
unsigned i; | ||
int copt; | ||
int baud=BAUD; | ||
unsigned int capwidth=0; | ||
unsigned int repwidth=0; | ||
unsigned int caplength=0; | ||
unsigned int count; | ||
unsigned int trigpos=0; | ||
char *vcdfile=NULL; | ||
char *timescale="1ns"; | ||
float freq=-1; | ||
|
||
unsigned char *workbuf; | ||
FILE *vfile; | ||
time_t rawtime; | ||
struct tm * timedata; | ||
int debugging=0; // undocumented ;-) | ||
|
||
|
||
|
||
if (argc<2) | ||
{ | ||
help(); | ||
} | ||
|
||
|
||
while ((copt=getopt(argc,argv,"DF:T:BWb:c:r:n:o:t:")) != -1) | ||
switch (copt) | ||
{ | ||
case 'D': | ||
debugging=1; | ||
break; | ||
case 'T': | ||
timescale=optarg; | ||
break; | ||
case 'F': | ||
freq=atof(optarg); | ||
freq=1.0/(freq*.000002); // double plus microseconds to picoseconds | ||
break; | ||
|
||
case 'B': | ||
bflag=1; | ||
break; | ||
case 'W': | ||
bflag=2; | ||
break; | ||
|
||
case 'b': | ||
baud=atoi(optarg); | ||
break; | ||
case 'c': | ||
capwidth=atoi(optarg); | ||
if (capwidth>sizeof(uint64_t)) sizerr("Capture width"); | ||
break; | ||
case 'r': | ||
repwidth=atoi(optarg); | ||
if (repwidth>sizeof(uint64_t)) sizerr("Replacement width"); | ||
break; | ||
case 'n': | ||
caplength=atoi(optarg); | ||
break; | ||
case 'o': | ||
vcdfile=optarg; | ||
break; | ||
case 't': | ||
trigpos=atoi(optarg); | ||
break; | ||
|
||
default: | ||
case '?': | ||
help(); | ||
break; | ||
} | ||
|
||
count=(capwidth+repwidth)*caplength; | ||
if (count<=0) | ||
{ | ||
fprintf(stderr,"You must specificy the number of bytes in the capture (-c),\n" | ||
"the number of repeat count bytes in the capture (-r),\n" | ||
"and the total number of capture samples (-n)\n"); | ||
exit(3); | ||
} | ||
|
||
workbuf=(char *)malloc(count); | ||
if (!workbuf) | ||
{ | ||
perror("Out of memory"); | ||
exit(4); | ||
} | ||
|
||
if (vcdfile) | ||
vfile=fopen(vcdfile,"w"); | ||
else | ||
vfile=stdout; | ||
if (!vfile) | ||
{ | ||
perror(vcdfile); | ||
exit(6); | ||
} | ||
|
||
|
||
err=sp_get_port_by_name(argv[optind],&port); | ||
if (err==SP_OK) | ||
err=sp_open(port,SP_MODE_READ_WRITE); | ||
if (err!=SP_OK) | ||
{ | ||
fprintf(stderr,"Can't open port %s\n",argv[1]); | ||
exit(2); | ||
} | ||
sp_set_baudrate(port,BAUD); // TODO: Command line option | ||
// write reset | ||
i=USERCMD_RESET; | ||
sp_blocking_write(port,&i,1,100); | ||
// write run | ||
i=USERCMD_RUN; | ||
sp_blocking_write(port,&i,1,100); | ||
// read data (note data is backwards!) | ||
for (i=0;i<count;i++) | ||
{ | ||
int waiting; | ||
int c; | ||
do | ||
{ | ||
waiting=sp_input_waiting(port); | ||
} while (waiting<=0); | ||
sp_nonblocking_read(port,(void *)&c,1); | ||
workbuf[(count-1)-i]=c; | ||
} | ||
sp_close(port); | ||
|
||
if (debugging) | ||
{ | ||
int q; | ||
FILE *dfile=fopen("debug.txt","w"); | ||
for (q=0;q<count;q+=3) | ||
{ | ||
// only works for specific format -c 2 -r 1 | ||
fprintf(dfile,"%02X: %02X %02X %02X\n",q/3,workbuf[q],workbuf[q+1],workbuf[q+2]); | ||
} | ||
fclose(dfile); | ||
} | ||
|
||
fprintf(stderr,"Writing vcd file\n"); | ||
fprintf(vfile,"$version la2vcd 0.1 $end\n"); | ||
|
||
time(&rawtime); | ||
timedata=localtime(&rawtime); | ||
fprintf(vfile,"$date %s $end\n",asctime(timedata)); | ||
fprintf(vfile,"$timescale "); | ||
if (freq!=-1) fprintf(vfile,"%.0fps",freq); | ||
if (freq==-1) fprintf(vfile," %s",timescale); | ||
fprintf(vfile," $end\n"); | ||
fprintf(vfile,"$scope module CAPTURE $end\n"); | ||
// Need to have a definition file or something for this but for now... | ||
fprintf(vfile,"$var wire 1 ! clk $end\n"); | ||
if (bflag&2) fprintf(vfile,"$var wire %u # capdata $end\n",capwidth*8); | ||
fprintf(vfile,"$var wire 1 ^ triggered $end\n"); | ||
if (bflag&1) for (i=0;i<capwidth;i++) fprintf(vfile,"$var wire 8 %c capbyte%u $end\n",'&'+i,i); | ||
|
||
fprintf(vfile,"$upscope $end\n"); | ||
fprintf(vfile,"$enddefinitions $end\n"); | ||
|
||
uint64_t t=0; | ||
unsigned linewidth=capwidth+repwidth; | ||
uint64_t rct=0; | ||
uint64_t data=0; | ||
unsigned j; | ||
|
||
fprintf(vfile,"$dumpvars\n0!\n0^\n"); | ||
if (bflag&2) fprintf(vfile,"bx #\n"); | ||
if (bflag&1) for (i=0;i<capwidth;i++) fprintf(vfile,"bx %c\n",'&'+i); | ||
fprintf(vfile," $end\n"); | ||
uint64_t tail0,tail; | ||
getbline(capwidth,repwidth,workbuf,(caplength-1)*linewidth,&tail,&rct); // rct not used here | ||
tail0=tail++; | ||
while (tail!=trigpos) | ||
{ | ||
// output oldest part of buffer | ||
getbline(capwidth,repwidth,workbuf,tail*linewidth,&data,&rct); | ||
if (rct==0) break; | ||
writeline(vfile,&t,rct,data,0,capwidth); | ||
tail++; | ||
} | ||
tail=0; | ||
while (tail<=tail0) | ||
{ | ||
// output newer part of buffer | ||
getbline(capwidth,repwidth,workbuf,tail*linewidth,&data,&rct); | ||
if (rct==0) break; | ||
writeline(vfile,&t,rct,data,0,capwidth); | ||
tail++; | ||
} | ||
// now do the rest | ||
for (i=trigpos;i<caplength-1;i++) | ||
{ | ||
getbline(capwidth,repwidth,workbuf,i*linewidth,&data,&rct); | ||
if (rct==0) break; | ||
writeline(vfile,&t,rct,data,i==trigpos,capwidth); | ||
} | ||
|
||
|
||
|
||
|
||
if (vfile != stdout) fclose(vfile); | ||
if (workbuf) free(workbuf); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
This is a simple utility to capture data from openverifla and dump it directly to a vcd. | ||
|
||
=== Compile | ||
Should compile with any normal C compiler where libserialport is available (get from Sigrok). | ||
You do need a recent version of libserialport -- the one currently in Ubunut repos will not work. | ||
|
||
gcc -o la2vcd la2vcd.c -lserialport | ||
|
||
=== Usage | ||
Usage: la2vcd [-B] [-W] [-F frequency] [-T timescale] -b baud, -t trigger_pos -c cap_width, -r repeat_width, -n samples -o vcd_file port_name | ||
|
||
You need all the lower case options, although baud will default to 9600 | ||
|
||
-B output only bytes of capture | ||
|
||
-W output only words (default is both bytes and words) | ||
|
||
-F sets frequency in MHz (e.g., -F 250). | ||
|
||
Or you can set the timescale (e.g, -T 1ns) with -T. Note the timescale should be twice the clock frequency. Default to 1nS and you do your own math. | ||
|
||
Great idea to build a script with all the "standard" settings for a project: | ||
|
||
#!/bin/bash | ||
exec la2vcd -W -F 50 -b 57600 -t 129 -c 3 -r 1 -n 256 -o "$1" | ||
|
||
Just as an example. | ||
|
||
Al Williams [email protected] |
Oops, something went wrong.