## Where communities thrive

• Join over 1.5M+ people
• Join over 100K+ communities
• Free without limits
##### Activity
Lawrie Griffiths
@lawrie

module LEDglow(clk, LED);
input clk;
output LED;

reg [27:0] cnt;
always @(posedge clk) cnt<=cnt+1;

wire [3:0] PWM_input = cnt[27] ? cnt[26:23] : ~cnt[26:23];
reg [4:0] PWM;
always @(posedge clk) PWM <= PWM[3:0]+PWM_input;

assign LED = PWM[4];
endmodule
Here is my attempt in Silice:
algorithm main(output uint$NUM_LEDS$ leds) {
uint28 cnt = 0;
uint5 pwm = 0;
uint4 pwm_input := cnt[27,1] ? cnt[26,4] : ~cnt[26,4];

leds[1,7] := 0;
leds[0,1] := ~pwm[4,1];

while (1) {
cnt = cnt + 1;
pwm = pwm[3,4] + pwm_input;
}
}
That does not work as it does not use the clock.
What am I doing wrong?
Lawrie Griffiths
@lawrie
(That example originally came from fpga4fun - https://www.fpga4fun.com/Opto0.html).
Lawrie Griffiths
@lawrie
This is my attempt with a configurable number of bits for the counter (also does not work):
$$bits = 24 algorithm main(output uintNUM_LEDS leds) { uintbits cnt = 0; uint5 pwm = 0; uint4 pwm_input := cnt[bits-1,1] ? cnt[bits-2,4] : ~cnt[bits-2,4]; leds[1,7] := 0; leds[0,1] := ~pwm[4,1]; while (1) { cnt = cnt + 1; pwm = pwm[3,4] + pwm_input; } } sylefeb @sylefeb @lawrie Made a quick test, it seems the issue is that the ranges you specified are out of bounds, e.g. cnt[26,4] is a four bit width uint extracted from bit 26 to 29 (while cnt has only 28 bits). Silice linter is being revised to incorporate this check, but another way to spot it is to do make verilator (same for pwm[3,4] => pwm being five bits this goes out of bounds) Lawrie Griffiths @lawrie Ah, I see, I misunderstood the numbering of the bits in swizzling. I thought it was more like Verilog. This version works: $$bits = 26

algorithm main(output uint$NUM_LEDS$ leds) {
uint$bits$ cnt = 0;
uint5 pwm = 0;
uint4 pwm_input := cnt[$bits-1$,1] ? cnt[$bits-5$,4] : ~cnt[$bits-5$,4];

leds[1,7] := 0;
leds[0,1] := pwm[4,1];

while (1) {
cnt = cnt + 1;
pwm = pwm[0,4] + pwm_input;
}
}
Lawrie Griffiths
@lawrie
And this version makes all the leds glow:
$$bits = 26 algorithm main(output uintNUM_LEDS leds) { uintbits cnt = 0; uint5 pwm = 0; uint4 pwm_input := cnt[bits-1,1] ? cnt[bits-5,4] : ~cnt[bits-5,4];$$for i = 0, NUM_LEDS-1 do
leds[$i$,1] := pwm[4,1];
end

while (1) {
cnt = cnt + 1;
pwm = pwm[0,4] + pwm_input;
}
}
Lawrie Griffiths
@lawrie
I have started a repository of my Silice examples, and here is a PS/2 keyboard test that appears to read scan codes from a PS/2 keyboard using a Digilent PS/2 PMod. I know @rob-ng15 was having problems with PS/2 keyboards.
@sylefeb To use a PS/2 keyboard on the US2 connector, we would need a new ifdef, say US2_PS2 in your top-level Verilog module for the Ulx3s, which declares the ports for the US2 connector and sets the pull-up resistors for PS/2.
Lawrie Griffiths
@lawrie
PS/2 keyboard are useful, particularly for retro computer implementations on the Ulx3s, and they are most conveniently used by plugging in a USB keyboard that supports PS/2, using the US2 connector.
USB keyboards can also be supported but it is a lot more code and not that reliable.
sylefeb
@sylefeb
@lawrie just tried the led glow, great example! Nice use of the pre-processor. You could also write leds := {$NUM_LEDS${pwm[4,1]}}; (akin to Verilog replication)
PS/2 sounds great! will add the define.
sylefeb
@sylefeb
I see in the lpf that the US2 connector has six pins, two differential inputs (usb_fpga_dX) and four inouts (usb_fpga_bd_dX/usb_fpga_pu_dX). How should these be exposed for the PS/2 keyboard? (in particular, do we keep the differential pair as a true differential LVCMOS33D?)
Rob S
@rob-ng15
Thanks @lawrie , that looks incredibly helpful. I still need to get another PS2 keyboard to try it with.
Lawrie Griffiths
@lawrie
@sylefeb Here is an example of a PS/2 keyboard in Verilog - https://github.com/lawrie/ulx3s_z80_template/blob/main/src/top.v#L187-L202
It uses usb_fpga_bd_dp for the clock and usb_fpga_bd_dn for the data, and both the pullups are set high.
Lawrie Griffiths
@lawrie
@sylefeb I remain very confused about the semantics of Silice. I imagined that continuous assignment with the := operator were combinatorial. But in section 4.7 of the manual, you say These assignments are performed immediately after each rising clock and are order dependent., which implies they are synchronous. Which is it, or can they be either?
You also say that the always block is combinatorial, but the examples seem to contradict that, for example increasing counters in the uart example https://github.com/sylefeb/Silice/blob/master/projects/common/uart.ice#L66
Also, in that uart example, I am confused by the setting of uart_tx after the always block - https://github.com/sylefeb/Silice/blob/master/projects/common/uart.ice#L79
What relationship does that have to the assignments of uart_tx within the block?
Lawrie Griffiths
@lawrie
(Incidentally when I tried your uart echo example on the Ulx3s, it appeared to lose characters. Sending "Hello" echoed "Hlo").
So, if always can contain synchronous logic, what is the difference between while (1) {...} and always [ ...]?
When I tried changing while (1) to always in my led_glow example, I got an error message about in_run.
emard
@emard
@sylefeb I applied 6 pins to USB to be able to control all pullups, have differential inputs and single ended bidirectionals at the same time as USB protocol demands all this electrically. You can use any combination you find working best (sometimes routing paths make difference). In all devices I tried, differential is not needed but provides slightly cleaner signal with less error retries
sylefeb
@sylefeb
@lawrie I had made this introduction video that might help clarify: https://www.youtube.com/watch?v=_OhxEY72qxI ; your feedback made me realize it may indeed be confusing for those familiar with Verilog to transition to Silice, will add notes on that in the repo. Basically everything you write is combinatorial (ends up in a Verilog always@* with = assignments) but variables are turned into flip-flops as needed. So if you write a = a + 1 it becomes a_d = a_q + 1 with a_q <= a_d in a posedge block. Code is split into FSM states as required (with predictable rules so you can try to minimize/avoid that).
Silice always blocks are statements applied at every clock, before any of the other states. This is useful for instance to monitor an input pulsing high, while the rest of the logic/FSM is being run. Also, the idea is to help progressively go from a FSM style (with while / ++: / subroutines ) to a more compact 'always' style.

When I tried changing while (1) to always in my led_glow example, I got an error message about in_run

Ah, you've just hit a bug: sylefeb/Silice#113 This would work in any algorithm other than main ... will fix!

sylefeb
@sylefeb
@emard @lawrie US2: thanks, will push a first attempt on 'wip'. inout are still a bit difficult to use in Silice (requires a small Verilog glue), also something to be improved (sylefeb/Silice#19), so I'll probably specialize to PS/2 for now.

Incidentally when I tried your uart echo example on the Ulx3s, it appeared to lose characters.

Oh no, I thought this one was stable! will investigate sylefeb/Silice#117

sylefeb
@sylefeb

What relationship does that have to the assignments of uart_tx within the block?

The always block is specified before any other code. So besides the always block this uart_tx=1 is the only thing performed by the algorithm, and only once (while the always block remains always active). This was used to initialize the output to 1 -- no longer necessary, Silice now supports the syntax output uint1 uart_tx = 1.

sylefeb
@sylefeb

@lawrie pushed the us2_ps2 addition, Makefile change: silice-make.py -s blinky.ice -b $@ -p basic,us2_ps2 ...main becomes: algorithm main( output uint$NUM_LEDS\$ leds,
input  uint1 us2_bd_dp,
input  uint1 us2_bd_dn,

usb_fpga_pu_dp/usb_fpga_pu_dn are assigned 1. Hope this works!

Rob S
@rob-ng15

Hi Sylvain,

I've been waiting for you to do that! I have those set in my ulx3s.v for a while during testing :)

I'm just trying to wire in the ps2.ice from @lawrie to see how it goes. I'm wiring it to the USB pins. I'll let you know.
sylefeb
@sylefeb
Hi Rob - thanks! looking forward to the PS/2 keyboard working, will be very useful (plus we can put all these old keyboards to good use!).
Rob S
@rob-ng15

Well the first step is to get it to give the same output 0xaa as I get using the keyboard I have. I've got to get a working PS2 keyboard for the ulx3s. Just catching up with the changes that have been made in Silice since I last updated. Mainly, changes to the bram interface passing at the moment.

Just looking at the audo_pwm.ice... THAT I definitely have a use for :)

Rob S
@rob-ng15
Excellent news! The modified PS2 code from Lawrie that I integrated into PAWS gives the same 0xaa code as his original verilog code, so I take that as a good sign :)
Lawrie Griffiths
@lawrie
@sylefeb us2_ps2 worked for me as well. I can see PS/2 scan codes from a keyboard connected to us2.
I checked the uart_echo test on the Wip branch as it might have been the main branch I tried it on before, but I still see the problem. I run stty -F /dev/ttyUSB0 raw -echo 115200; cat /dev/ttyUSB0 on one terminal and echo Hello >/dev/ttyUSB0 on another, and every other character is lost.
Lawrie Griffiths
@lawrie
@sylefeb I am familiar with languages that have different semantics to Verilog. In migen and nmigen you have to be explicit about whether every statement in synchronous or combinatorial (by adding them to the appropriate domain). In SpinalHDL you have to be explicit about which signals are flip-flops (Reg) and it then generates synchronous code for the registers. But Silice has different semantics that doesn't really conform to the combinatorial/synchronous distinction, so I think some of the references to combinatorial logic in your manual are confusing.
Rob S
@rob-ng15
@lawrie @sylefeb The modified ps2.ice that I integrated into PAWS is here: https://github.com/rob-ng15/Silice-Playground/blob/master/PAWS/common/ps2.ice the main change being to remove from main and input the data and clock lines rather than the whole gpio.
PAWS is now caught up with the Silice WIP branch :)