Blackie Beard said:
Can you give me link to familiarize myself with "cycle c"?
Never heard of it before.
Regards,
BB
I never looked at google but there's probably something there to read.
Since C is generally free or low cost most companies will use C in
different ways so these Cycle Cs are nonstandard.
You also have the VCS compile to C option, and in the past I used a
homebrew Verilog2C compiler. The resulting C was usually a few x
slower than custom C and not very comprehensible. There is also
SystemC.
Since C is not a HDL and Verilog is not a gen purpose programming
language there are constraints when using only one but there are
issues if you use both.
For the cpu I am working on which is < few K lines of HDL as well as
the C compiler for it, I do the following.
I forgo hierarchy since I also have to do layout, I need control of
all final placement with hierarchy getting in the way. For a larger
project this gets very hard. This is an FPGA not an ASIC and 1 person
not a large team.
I have a top level Verilog module that includes 3 files, nets.v,
assign.v and always.v. The C source is almost the same, a main
including nets.c, assign.c & always.c.
There are also some define files that lets the net.v file declare all
the wires and busses using something like
wire16 which is changed to wire [15:0] etc for all the sizes needed.
The nets.c file can now use the same declarations as the verilog with
some changes. Arrays are special case again but most nets are not
arrays.
The reg vars are done in same way. In the def.h file both wire16 and
reg16 just become ulong. That means another limit, nothing bigger than
32b. Tough.
The assign file will hold all continuosly assigned expressions off 1
assign keyword. In Verilog these will be comma separated
assign
a = b, c= d,,,,,, etc ;
In C this is almost exactly the same since many comma sep exprns are
allowed.
assign // assign is defined as null
a = b, c= d,,,,,, etc ;
The big difficulty here is bit level twiddling and use of {,,} and [:]
and literal constants etc. For each case the code will be different,
but most simple nets can be assigned with same code.
Also use lots of ()? as syntax is same, these will usually become
muxes.
By definition the ordering of exprns in an always is unimportant in
Verilog since they are event driven by the simulator, but the C
compiler will eval them in order written.
That means no cycle graphs can be allowed, every assigned var must be
written before any use of that var and vars can only be assigned once.
So the Verilog is forced to be in time event order as you expect
signal propagation. This can get tough because now you need to think
about what the schematic would look like for the signal propagation.
For an FPGA there will be a constraint than no more than N assigns can
stack up before the next flop where gate depth complexity is < some
limit.
The always is the same sort of thing but this time we want edge
triggered flops vars. Either these can be explicitly made with 2
assignments which can have the masters in any order, followed by all
the slaves copies at the end hidden away.
To be cheap & fast and to make V & C code more similar, I do the
master/slave in 1 go by writing all assignments to flops in time
reverse order.
Verilog doesn't care about the order of always statements, one might
prefer to write in the pipeline order flow, but for C that would
produce a big tunnel short across the pipeline.
So Verilog looks like
always ... begin
p3<=p2;
p2<=p1;
p1<=p0;
end
and C looks like same with always, begin, end defined as null,{,}
always ... begin
p3<=p2;
p2<=p1;
p1<=p0;
end
The expressions that are included here follow same rules as for
assign. The same problem still persists with {,,,} [:] bit twiddling
in Verilog since that must also be turned into shifts & mask &s.
In some cases its not possible to do this master slave backwards with
1 always write. IF you have a 4stage circular pipeline with logic
between each stage, there is no logical end. One pipe must be noted as
the end and its value can be assigned redundantly to an output net
back over to the assign side. Now the next pipeline stage assigns from
that net. Thats a hidden explicit master slave but using a reg and a
net to hide it. Verilog & C don't care about redundant expressions,
both compiler will remove them
The C main includes the fake clock loop
#include defs.h
#include nets.c
for (i=0;i<umpteen_clocks;i++) {
#include assign.c // most computational logic
fprintf(fp,"..",,,,); // lots of output goes here
#include always.c // clock edge is effective here
}
Given the above, the verilog is fully synthesizeable and the C can
cope with most of it pretty well. The 2 net files are almost identical
except arrays.
There is the issue of whether an expression should be placed in mostly
the assign or the always side. If the expression has fanout >1 it must
be in the assign side. In FPGA synthesis I sometimes sees different
synthesis results depending on which side it is placed even if the sim
result is same.
No hierarchy, single clock domain, 32b widths & less, {,,} [:] issues
but I expect the C to simulate maybe 100 x faster. It also has the
advantage that a 2nd non RTL C model can also be included with no pain
to verify the RTL model. In fact the compiler for the cpu could also
be included to generate code for the ISA and be simulated on the
models. Think of java/Jit/JVM here, cpu is the JVM.
hope that helps
johnjakson_usa_com