To this end I wired a debounced signal from the iCEbreaker user button (the one near the usb connector) to the reset wire we already have in place for all the modules.
The debounce module was copied from Nandland and adapted to be be usable for negative logic buttons as well (the use button is high when not being pressed).
We don't want to fire reset_button events every clock cycle as long as the button is pressed so we keep some state and only generate a reset_button event when the state changes from not pressed to pressed. The code is committed to the repository and shown below. The idea is to make the other buttons on the iCEbreaker board available to the cpu via a memory mapped interface.
// button wires
wire user_button, button1, button2,button3;
debounce #(.INITIAL_STATE(1'b1)) debounce_ubutton(CLK, BTN_N, user_button);
reg reset_button = 0;
reg user_button_pressed = 0;
always @(posedge CLK) begin
reset_button <= 0;
if(~ user_button & ~user_button_pressed) begin // pressed (negative logic)
user_button_pressed <= 1;
reset_button <= 1; // a one clock strobe on pressing
end else begin
user_button_pressed <= 0;
end
end
The u_error signal from the UART is now integrated in the the reset logic which makes it also possible to reset things by sending a break over the serial connection. (the UART core used does no provide separate break signals but sets u_error on a received break)
// global reset active low, cleared after startup, set on serial break or user button press
reg reset = 0;
always @(posedge CLK) begin
reset <= 1;
if(u_error | reset_button) reset <= 0;
end