Since the COVID-19 pandemic, I'm teaching Verilog lab online. I let each student remotely connect to a computer having Xilinx Vivado installed, a Basys 3 board connected and powered on, and a camera that see the board so they can see the results on LEDs and the seven-segment display.
I'm preparing a lab about Counters, but I've an issue with how to remotely handle the reset signal. Do you have any thoughts that can help here, instead of relying on a physical toggle button due to remote access?
-
\$\begingroup\$ how is the remote connection made? \$\endgroup\$jsotola– jsotola2020年04月15日 17:00:06 +00:00Commented Apr 15, 2020 at 17:00
-
\$\begingroup\$ I've edited the title to be more clear. Remotely, we can only see the board through camera and program it using remote desktop having Vivado. We can't toggle switches or use the bush buttons remotely. \$\endgroup\$Hesham Eraqi– Hesham Eraqi2020年04月15日 17:03:07 +00:00Commented Apr 15, 2020 at 17:03
-
\$\begingroup\$ How about a reset pulse which is enabled for 1 second every 60? Student can see counter getting reset, no interaction necessary. Or a serial port connected to the computer, use DTR as the reset signal and have some program the students can run which enables DTR for a second. \$\endgroup\$jonathanjo– jonathanjo2020年04月15日 17:05:08 +00:00Commented Apr 15, 2020 at 17:05
-
1\$\begingroup\$ are you able to toggle the scroll lock remotely? ... does the scroll lock light activate on a keyboard on your server? \$\endgroup\$jsotola– jsotola2020年04月15日 17:39:48 +00:00Commented Apr 15, 2020 at 17:39
-
1\$\begingroup\$ hack a keyboard ... use the scroll lock light to generate the reset signal \$\endgroup\$jsotola– jsotola2020年04月15日 18:12:10 +00:00Commented Apr 15, 2020 at 18:12
2 Answers 2
I found a workaround that allows me use a remote keyboard button that acts as a remote reset button press. For that I relied on the Basys 3 board shared UART/JTAG USB port, in other words I relied on the UART in the FTDI chip in the board.
I wrote a simple UART reciever module (the code is below) that detects the input received from the Windows COM port commands (I used Tera Term tool enter link description here). Once the ASCII value of a specific keyboard key is received ('a' in my code below), the module gives a short output pulse. Other modules can instantiate that module, and use that pulse generated remotely through keyboard as a reset signal.
The following picture shows how AnyDesk is used to remote access a lab machine for development and to see the connected Basys 3 board via camera, and Tera Term tool and the designed UART receiver are used to simulate board buttons presses remotely from my machine: enter image description here
This is the code:
module UART_receiver_for_reset( // UART (Asynchronous) receiver, that gives pulse on output_level when 'a' keyboard key ascii value is received
input clk, // input clock
//input reset, // reset should be normally an input wire that is used to initialize some registers to 0, but in our remote case we don't have access to any GPIOs to use for reset, so we specify reg initial values directly to 0 instead of waiting for a reset signal to do so (for example reg state = 0;), take care that a wire doesn't have storage so an initial value to it doesn't make sense.
input RxD, // input receiving data line
output [7:0] RxData, // output for 8 bits data
output output_level // output level
);
//internal variables
reg [3:0] bitcounter = 0; // 4 bits counter to count if 10 bits data transmission complete or not
reg [1:0] samplecounter = 0; // 2 bits sample counter to count up to 4 for oversampling
reg clear_bitcounter, inc_bitcounter, inc_samplecounter, clear_samplecounter; // clear or increment the counter
reg [13:0] counter = 0; // 14 bits counter to count the baud rate (symbol rate) for UART receiving
reg state = 0; // initial state variable (mealy finite state machine)
reg nextstate; // next state variable (mealy finite state machine)
reg shift; // signal to indicate shifting data is ready
reg [9:0] rxshiftreg; // 10 bits data needed to be shifted in during transmission. For storing the serial package and sending its bits one by one. The least significant bit is initialized with the binary value "0" (a start bit) A binary value "1" is introduced in the most significant bit
reg output_reset = 0; // our output reset
reg [31:0] time_counter = 0; // needed for our output reset
// Constants (a parameter infers its type from its value)
parameter clk_freq = 100_000_000; // system clock frequency
parameter baud_rate = 9_600; // baud rate (should be agreed upon with the transmitter)
parameter oversamples = 4; // oversampling
parameter reset_counter = clk_freq/(baud_rate*oversamples); // counter upper bound
// <------------ 100M clock cycles ----------->
// <------------ 9,600 bits ------------------>
// <------------ 9,600x4 samples ------------->
// reset_counter = 2604, means counter goes from 0 to 2604 (during that time I should take 1 sample)
parameter counter_mid_sample = (oversamples/2); // this is the middle point of a bit where you want to sample it
parameter num_bit = 10; // 1 start, 8 data, 1 stop
parameter reset_key = 8'b01100001; // 8'b01100001; is the binary value of the ASCII character of small 'a' keyboard button
parameter reset_high_seconds = 1;
parameter reset_time_counter = clk_freq*reset_high_seconds;
assign RxData = rxshiftreg [8:1]; // assign the RxData from the shiftregister
assign output_level = output_reset;
// UART receiver logic
always @ (posedge clk) begin
counter <= counter +1; // start count in the counter
if (counter >= reset_counter-1) begin // if counter reach the baud rate with sampling
counter <=0; //reset the counter
state <= nextstate; // assign the state to nextstate
if (shift)rxshiftreg <= {RxD,rxshiftreg[9:1]}; //if shift asserted, load the receiving data
if (clear_samplecounter) samplecounter <=0; // if clear sampl counter asserted, reset sample counter
if (inc_samplecounter) samplecounter <= samplecounter +1; //if increment counter asserted, start sample count
if (clear_bitcounter) bitcounter <=0; // if clear bit counter asserted, reset bit counter
if (inc_bitcounter)bitcounter <= bitcounter +1; // if increment bit counter asserted, start count bit counter
end
// Handle our desired reset output
if (output_reset == 0 && rxshiftreg[8:1] == reset_key)
output_reset <= 1;
if (output_reset == 1)
if (time_counter >= reset_time_counter) begin
time_counter <= 0;
output_reset <= 0;
rxshiftreg[8:1] <= 0;
end
else time_counter <= time_counter +1;
end
// Finite state machine
always @ (posedge clk) begin //trigger by clock
shift <= 0; // set shift to 0 to avoid any shifting
clear_samplecounter <=0; // set clear sample counter to 0 to avoid reset
inc_samplecounter <=0; // set increment sample counter to 0 to avoid any increment
clear_bitcounter <=0; // set clear bit counter to 0 to avoid claring
inc_bitcounter <=0; // set increment bit counter to avoid any count
nextstate <=0; // set next state to be idle state
case (state)
0: begin // idle state
if (RxD) // if input RxD data line asserted
nextstate <=0; // back to idle state because RxD needs to be low to start transmission
else begin // if input RxD data line is not asserted
nextstate <=1; // jump to receiving state
clear_bitcounter <=1; // trigger to clear bit counter
clear_samplecounter <=1; // trigger to clear sample counter
end
end
1: begin // receiving state
nextstate <= 1; // DEFAULT
if (samplecounter == counter_mid_sample - 1) shift <= 1; // if sample counter is 1, trigger shift
if (samplecounter == oversamples - 1) begin // if sample counter is 3 as the sample rate used is 3
if (bitcounter == num_bit - 1) // check if bit counter if 9 or not
nextstate <= 0; // back to idle state if bit counter is 9 as receving is complete
inc_bitcounter <=1; // trigger the increment bit counter if bit counter is not 9
clear_samplecounter <=1; //trigger the sample counter to reset the sample counter
end
else inc_samplecounter <=1; // if sample is not equal to 3, keep counting
end
default: nextstate <=0; //default idle state
endcase
end
endmodule
module my_module(input clk, RxD); // also add your other inputs and outputs here
wire reset;
UART_receiver_for_reset (.clk(clk), .RxD(RxD), .RxData(), .output_level(reset))
//...your module code...
endmodule
-
1\$\begingroup\$ This really is excellent. Super to see teachers working on ways to keep the students learning even when they can't get to the physical lab. I'd consider Arduino "beetle" style, recognising hex digits and outputting 4 logic lines: tiny, and completely portable to all kinds of external circuit. \$\endgroup\$jonathanjo– jonathanjo2020年04月18日 19:36:41 +00:00Commented Apr 18, 2020 at 19:36
A USB-controlled relay would do the job. At my work, we’ve used them to cycle power and/or reset for test fixtures.
If your JTAG adapter has an extra GPIO that could be used as well, via tcl script. Try here: https://forums.xilinx.com/t5/FPGA-Configuration/Reboot-Zynq7020-with-JTAG-SmartLynq/m-p/1071176
-
\$\begingroup\$ Thanks a lot. The first solution is good but I would like to learn more about the second because I prefer more pervasive solutions. The Basys 3 board (reference.digilentinc.com/_media/basys3:basys3_rm.pdf) uses a shared UART/JTAG USB port, so I think yes it's applicable in my case. I would appreciate it if you can provide more info or a reference regarding setting GOP's using for example ftdichip.com/Drivers/VCP.htm. \$\endgroup\$Hesham Eraqi– Hesham Eraqi2020年04月15日 18:31:53 +00:00Commented Apr 15, 2020 at 18:31
-
\$\begingroup\$ You always have the option of forcing a reconfiguration from Vivado. This will reset a wedged device. But it doesn’t model a design-scope reset once the device is configured and running, which is what I think you’re a asking for. This would need a specific ‘normal’ I/O pin to be the designated reset. \$\endgroup\$hacktastical– hacktastical2020年04月15日 18:37:44 +00:00Commented Apr 15, 2020 at 18:37
Explore related questions
See similar questions with these tags.