-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
General code issues thread #108
Comments
The syntax for the subroutine call is: Something else, more related to timing -- in this part: Clocks = Clocks + 1;
if ( Clocks == $ClocksPerMS$ ) {
// ...
} It is best to increment (Edit:) the same is true for |
Thank you for the feedback! That being said, I'm still having trouble getting WaitForRisingEdge to work:
I'm not sure if its a code problem or FPGAs being a bit unfamiliar. |
I think I see the problem. When you call a subroutine it copies its arguments - precisely to avoid them changing while it processes. This is why Two possible approaches. 1) Incorporate the subroutine in the algorithm (which they are meant to be), so you can actually access the algorithm internals. This becomes: algorithm main( output uint$NUM_LEDS$ leds, output uint$NUM_GPIO_OUT$ gp, input uint$NUM_GPIO_IN$ gn ) {
uint1 FilteredButton = 0;
uint1 Button = 0;
uint1 State = 0;
uint1 ADebug = 1;
subroutine WaitForRisingEdge( reads FilteredButton ) {
uint1 Exit = 0;
uint1 Last = 0;
Last = FilteredButton ;
while ( Exit == 0 ) {
Exit = ( Last == 0 && FilteredButton == 1 ) ? 1 : 0;
Last = FilteredButton;
}
}
Debounce Btn(
Source <: Button,
Dest :> FilteredButton
);
Button := gn[ 10,1 ];
leds[ 0,1 ] := ADebug;
gp[ 0,1 ] := State;
while ( 1 ) {
ADebug = 1;
( ) <- WaitForRisingEdge <- ( );
ADebug = 0;
State = ~State;
}
} Note the explicit declaration The other option is to turn algorithm WaitForRisingEdge( input uint1 FilteredButton ) {
uint1 Exit = 0;
uint1 Last = 0;
Last = FilteredButton ;
while ( Exit == 0 ) {
Exit = ( Last == 0 && FilteredButton == 1 ) ? 1 : 0;
Last = FilteredButton;
}
}
algorithm main( output uint$NUM_LEDS$ leds, output uint$NUM_GPIO_OUT$ gp, input uint$NUM_GPIO_IN$ gn ) {
uint1 FilteredButton = 0;
uint1 Button = 0;
uint1 State = 0;
uint1 ADebug = 1;
Debounce Btn(
Source <: Button,
Dest :> FilteredButton
);
WaitForRisingEdge waitedge(
FilteredButton <: FilteredButton, // parameter binding
);
Button := gn[ 10,1 ];
leds[ 0,1 ] := ADebug;
gp[ 0,1 ] := State;
while ( 1 ) {
ADebug = 1;
() <- waitedge <- (); // no input parameter as it is bound
ADebug = 0;
State = ~State;
}
} When a parameter is bound it tracks the value of the source (connected through a wire in terms of hardware). Note that there are two bindings: |
I have done some testing with generating delays, it seems like ones done inline are accurate while wrapping them in a subroutine causes problems. For example, if I have a counter in my main loop and toggle a pin whenever the counter reaches 4 then I get a 250ns signal which is what I would expect from a 16MHz clock. Maybe I'm just approaching this wrong and there is a more correct way to accurately handle timing? |
Hi - the timing would have to account for the subroutine entry/exit cycles. This is partially discussed in Section 5 but I really have to revise this with more examples and diagrams, that is an important topic. So for instance, let's consider this subroutine wait(input uint16 incount)
{
uint16 count = uninitialized;
count = incount;
while (count != 0) { count = count - 1; }
}
algorithm main( output uint$NUM_LEDS$ leds,input uint1 btns )
{
uint16 cycle = 0;
always { cycle = cycle + 1; }
__display("[before] cycle %d",cycle);
() <- wait <- (0);
__display("[next ] cycle %d",cycle);
() <- wait <- (4);
__display("[done ] cycle %d",cycle);
} Now simulating with icarus
So we can see the subroutine call, even with a 0 parameter takes 4 cycles. With an input of 4 it then takes 8 cycles. So there is an overhead of four: 2 for entry/exit of subroutine and 2 for the entry/exit of the while. Note that there are chain rules, so adding a while right after the other will add a single cycle instead of 2 (clarifying the documentation right now!). What if we want a less than 4 cycles wait? We can use multiple Taking these delays into account should give you the exact timing. .DEFAULT: test.ice
silice-make.py -s test.ice -b $@ -p basic -o BUILD_$(subst :,_,$@)
clean:
rm -rf BUILD_* |
Ohhhh okay! I don't think I was taking into account not only that entering and exiting the subroutine were taking cycles, but that the main loop was adding some delay as well. Thank you :) |
Hello, I am a Silice and FPGA newbie and have a question regarding readwrite permissions on subroutines. In the following example the subroutine out_led is called by the subroutine out_led_inverted. For this, the subroutine out_led_inverted needs to get permission to access the parameter pattern from out_led.
But the syntax for this is not clear to me. Only from the compiler error message "variable 'i_out_led_pattern' is written by subroutine 'out_led_inverted' without explicit permission" I could recognize the name for this parameter. Is this intentional or did I miss something? Regards, Bernd. |
Hello Bernd, The error message is indeed not useful, I'll improve that. The subroutine Silice/tests/issues/108_rw_perm.ice Line 9 in 5fa9ed9
Welcome to Silice! |
Improved error message (in
Thanks for pointing this out!! |
Hello Sylvain, thank you for the explanation. It works perfectly. Regards, Bernd. |
Hello, I am trying to bind two pmod bits, one as input and the other one as output, to an algorithm. The input binding "bit_in <: pmod.i[0,1]" seems to work, but the output binding "bit_out :> pmod.o[1,1]" leads to an error: "cannot find accessed base.member 'pmod.o'". For sure, this is a beginner question. But I cannot see, how to solve this.
Regards, Bernd. |
Hi Bernd, Your syntax makes perfect sense, unfortunately you've hit a limitation on output bindings (see #208). The error message is not helpful and I'll improve that shortly (ultimately the syntax your are using will be supported). The good news is, there are simple workarounds, see https://github.com/sylefeb/Silice/blob/draft/tests/issues/108_pmod.ice Thanks for the report! |
Partially fixed the issue:
Changes in |
Hello Sylvain, thank you for the answer, for improving the Silice compiler and providing the workaround. Regards, Bernd. |
Hello Sylvain, can an inout pmod simply be used as a gpio? The following program should output four pulses on the icestick pmod (bit 0) and then read bit 1 (pulled up via a resistor) and output it on the LED. The program only works if the marked step is commented out. If the step is not commented out, then bit 1 is apparently not read in correctly. I suspect I am missing something significant, or may be the inout pmods can not be used this way?
Regards, Bernd. |
Hi Bernd - thanks for the report, I am looking into it! (I see the same behavior and it is indeed confusing). |
I believe I have identified the issue -- it's not obvious, and I am actually surprised by the behavior. Nevertheless I decided to modify the tristate so that the behavior is stable. This means introducing a one cycle latency between when .o / .oenable are set and the actual change on the pin, but that is anyway better in terms of managing IO skew/delays. The change is applied in the (Side note: instead of |
Hello Sylvain, thanks for tracking this down. I think I will wait for the master branch. Regards, Bernd. |
Hi Bernd, the single assignment should indeed be enough (and is enough after the fix), the best being a single The fact you needed multiple assignments was a side effect of the problem itself. |
Hello Sylvain, thank you for the explanation. I have come across the strange "pmod behavior" several times. I'm glad you were able to fix it. Regards, Bernd. |
Thanks a lot Bernd for the tests + reports (inouts are used in fewer designs, and tristates can be a bit tricky...). In general feel free to reach out if anything seems suspicious, I am happy to check. |
Hello Sylvain, I am having difficulties to get the dual ported BRAM working. The following design for the Icestick should use ICESTORM_RAM, but if I look into the log-file (next.log) I can see a utilization of 0 % for the RAM. I have the "simple_dualport_bram" working in another design, but this time I want to read from both ports.
I am not using the very latest version of yosys (0.20 ), nextpnr (0.3) and Silice. It would be nice if you could check if I did something wrong. Regards, Bernd. |
Hi Bernd, Just had a quick look, this is indeed odd. As a workaround comment I'll investigate further. Thanks for the report! |
Hello Sylvain, thank you. This works. I can read now over port 0 and read/write over port 1. Bonne année. Regards, Bernd. |
Hello Sylvain, the draft version behaves differently than the master version regarding local variables in subroutines. The master version compiles the following design without problems, the draft version throws an error in line 9:
Is this a problem of the draft version? Regards, Bernd. |
Hi Bernd - thanks for the report. Indeed this changed in draft but has to be revised. In general it is best to avoid shadowing a variable name, but I intend to issue a 'strong' warning as opposed to an error on such cases (and there are other similar cases that needs clarifying too). Sorry for the trouble, will try to look into it soon! (Opened new issue #250) |
Hi Bernd, this problem (name shadowing) should be fixed in master, please let me know in case of trouble. |
Hello Sylvain, I am trying to realize an 8 bit bidirectional data transfer with an ICE40 FPGA. The FPGA should read the external data with the falling edge of the clock.
Obviously I am doing something wrong. |
Hi Bernd, Sorry for the delay in answering. There is a limitation on tristate pins, they cannot be bound with a bit select (so the issue is
This is not great, I'll look into fixing this limitation! (opened issue #258). The error message also needs clarification. Thanks and best wishes for 2024! |
ok, I am going to take the breakout route then. So I can avoid Verilog. Have a good new Year. |
Hi Bernd, I have lifted this restriction (in draft branch), so that binding inouts with bit select is now possible. Please let me known if there's any trouble with it. |
Hello Sylvain, I am pleased that you have removed the bit select restriction and would like to try out the new version. But I have problems to compile the draft version of Silice. The master version compiles without problems. cmake throws a lot of warnings like:
And later the build fails with:
Regards, Bernd. |
Hello Sylvain, I used the Regards, Bernd. |
Hi Bernd, thanks! I'll be looking into this shortly (this is due to the compiler treating warnings as errors, I thought I fixed it but clearly the change did not propagate). |
Hello Sylvain, I am now using the new bit select "feature" to bind the inouts and my design is working. Thank you very much for implementing this. May be there is still a little problem, since Silice throws a lot of warnings that "bindings have inconsistent bit-widths", although the bit length is clearly one bit. Shall I open a new issue for this? Then I had to use the
And at last, I had to use the "dynamic linked variant" of Silice, which is produced with the master version of Regards, Bernd. |
Hi Bernd, Thanks for the report and for having gone through all the trouble, I'm working on fixing all these issues asap! Best, |
Hi Bernd, All of these issues are fixed in the To avoid the old silice executable to be in the path it may be best to remove it from The warning is fixed too. Hope that these changes will go smoothly! |
Hello Sylvain, I compiled the old way via /* Rant about Python removed ;-) */ There are still warnings left. Silice code:
I can provide a full test case, if you need it. Regards, Bernd. |
Hello sylefeb, I'm using Linux and starting to use Silice. In my first step, I tried to test it as you instructed: cd projects However, it shows me an error that it can't recognize the 'silice' command." , should i do something else after i cloned the repository and run ./get_started_linux.sh ? , its does not clear for me. |
Hello, did you run |
These last steps should no longer be necessary if using the |
That's great news! The fact that divstd_bare does not stop is not normal, and I can confirm I see the same issue; I'll fix it asap. Thanks for trying out Silice and for reaching out with these reports! |
by the way , now I'm working on project , that takes a system Verilog baseline that implement a vga draw and try to implement it in Silice and compare performance. |
On VGA there are multiple Silice examples, In terms of performance, are you looking at cycle counts, LUT count, max frequency? It is normally possible to reach the exact same result as Verilog, depending on which blend you choose between using alway blocks/algorithms/pipelines. Of course using the more flexible syntax can yield to overheads (but not always). For coding environment, I use vscode and there is a syntax coloring theme in |
New: the vscode extension is now part of the vscode library, and can be found in the Extensions tab of vscode (search for 'silice'). |
Thank you for your help in setting this up, Everything is working perfectly now. Your assistance was greatly appreciated! |
I'll start the first one:
In my attempt to debug WaitForRisingEdge by passing in a debug LED I now receive the following error message:
I've checked the documentation and examples a few times, and its not immediately obvious why this is coming up.
The text was updated successfully, but these errors were encountered: