// interrupts reg [2:0] int0; reg [2:0] int1; reg [2:0] int2; reg [1:0] int0_state; reg [1:0] int1_state; reg [1:0] int2_state; reg int_block; always @(posedge clk or negedge ena) // interrupt selectors if (!ena) int0 <= 3'b0; else if (go && setint0) // setint0 int0 <= d[2:0]; always @(posedge clk or negedge ena) if (!ena) int1 <= 3'b0; else if (go && setint1) // setint1 int1 <= d[2:0]; always @(posedge clk or negedge ena) if (!ena) int2 <= 3'b0; else if (go && setint2) // setint2 int2 <= d[2:0]; always @(posedge clk or negedge ena) // blocki/allowi if (!ena) int_block <= 1'b0; else if (go && (blocki || allowi)) int_block <= blocki; wire [7:0] int_source = { brk_event, // interrupt sources wrl_event, rdl_event, fbw_event, xro_event, edg_event, per_event, 1'b0 }; wire int_qual = !int_block && // interrupts must not be blocked !blocki && // blocki must not be executing !altds && // altds must not be executing !rep && // rep must not be executing !repnz && // repeat-block must not be executing !augswx && // augs must not be executing or waiting !augdwx; // augd must not be executing or waiting wire int0_elink = int0_state == 2'b10; // interrupt 0 has 1st priority wire int1_elink = int1_state == 2'b10 && ~|int0_state; // interrupt 1 has 2nd priority wire int2_elink = int2_state == 2'b10 && ~|int0_state && ~|int1_state; // interrupt 2 has 3rd priority assign interrupt = int_qual && (int0_elink || int1_elink || int2_elink); // assert interrupt 'link' during qualified instruction cycle assign interrupti = { 20'b1010101_110_1111_111110, // interrupt-entry instruction, 'link $1Fx,$1Fx+1 wc,wz' int0_elink, int1_elink, 7'b0_111110, // for interrupt 0..2, d = $1F4, $1F2, $1F0 int0_elink, int1_elink, 1'b1 }; // for interrupt 0..2, s = $1F5, $1F3, $1F1 assign interruptp = |{int0_state, int1_state, int2_state}; // interrupt-pending sensor (used by waitint) wire intx_xlink = linkr && i[wc:im] == 3'b110 && i[s8:s3] == 6'b111110; // interrupt-exit instruction sensor, 'link x,$1Fx wc,wz' wire int0_xlink = intx_xlink && i[s2:s0] == 3'b100; // reti0 sensor 'link x,$1F4 wc,wz' wire int1_xlink = intx_xlink && i[s2:s0] == 3'b010; // reti1 sensor 'link x,$1F2 wc,wz' wire int2_xlink = intx_xlink && i[s2:s0] == 3'b000; // reti2 sensor 'link x,$1F0 wc,wz' always @(posedge clk or negedge ena) // interrupt states if (!ena) int0_state <= 2'b0; else int0_state <= go && setint0 ? 2'b00 // setint0, set idle : int0_state == 2'b00 && int_source[int0] ? go ? 2'b10 : 2'b01 // idle, wait for event : int0_state == 2'b01 && go ? 2'b10 // got event and not go, wait for go : int0_state == 2'b10 && go && int0_elink && int_qual ? 2'b11 // got event and go, wait for entry link : int0_state == 2'b11 && go && int0_xlink ? 2'b00 // isr executing, wait for exit link : int0_state; // no change always @(posedge clk or negedge ena) if (!ena) int1_state <= 2'b0; else int1_state <= go && setint1 ? 2'b00 // setint1, set idle : int1_state == 2'b00 && int_source[int1] ? go ? 2'b10 : 2'b01 // idle, wait for event : int1_state == 2'b01 && go ? 2'b10 // got event and not go, wait for go : int1_state == 2'b10 && go && int1_elink && int_qual ? 2'b11 // got event and go, wait for entry link : int1_state == 2'b11 && go && int1_xlink ? 2'b00 // isr executing, wait for exit link : int1_state; // no change always @(posedge clk or negedge ena) if (!ena) int2_state <= 2'b0; else int2_state <= go && setint2 ? 2'b00 // setint2, set idle : int2_state == 2'b00 && int_source[int2] ? go ? 2'b10 : 2'b01 // idle, wait for event : int2_state == 2'b01 && go ? 2'b10 // got event and not go, wait for go : int2_state == 2'b10 && go && int2_elink && int_qual ? 2'b11 // got event and go, wait for entry link : int2_state == 2'b11 && go && int2_xlink ? 2'b00 // isr executing, wait for exit link : int2_state; // no change