In this chapter, we will do for interrupts what we have done for polling in a previous chapter. Namely, we will write a SystemVerilog module which connects the three SystemVerilog modules for
- Bird CPU
- a 4×7 segment display as an output device,
- a switchbank as an input device
A switchbank that can send interrupts
Note that a switchbank working with interrupts does not have an a0 signal, as it has only a single register: a data register. It does not need a status register.
Note also that the interrupt signal works exactly like the least significant bit of the status register in the polling case. It is set when enter key is pressed and reset when the switchbank is read by the CPU (ie, when ack becomes 1)
module switchbank_int ( input clk, //--user side input [15:0]switches , input enter_key, //--cpu side input ack, output interrupt, output [15:0]data_reg ) ; logic [1:0]pressed; always_ff @(posedge clk) begin pressed <= {pressed[0],enter_key}; if ( ( pressed == 2'b10 ) && ( interrupt == 1'b0 ) ) begin interrupt <= 1'b1; data_reg <= switches; end else if ( ack && ( interrupt == 1'b1 ) ) interrupt <=1'b0; end initial begin data_reg = 16'h0000; end endmodule
Top module (or glue logic)
In our design, glue logic will have some additional duties compared to the polling case. It will again implement the memory map. But in addition to that, it will implement the PIC, or the programmable interrupt controller.
module main_module ( input clk, //---input from switchbank input [7:0] switches, //input from 16-bit switchboard input enter_key, //enter button //---output to seven segment display output logic [3:0] grounds, output logic [6:0] display ); //====memory map is defined here==== localparam BEGINMEM = 12'h000, ENDMEM = 12'h7ff, SWITCHBANK = 12'h900, SEVENSEG = 12'hb00; //====memory chip============== logic [15:0] memory [0:127]; //=====cpu's input-output pins===== logic [15:0] data_out; logic [15:0] data_in; logic [11:0] address; logic memwt; logic INT; //interrupt pin logic intack; //interrupt acknowledgement //======ss7 and switchbank===== logic [15:0] ss7_out, switch_in; //====== pic =============== logic irq0, irq1, irq2, irq3, irq4, irq5, irq6, irq7; //=====components================== sevensegment ss1 (.datain(ss7_out), .grounds(grounds), .display(display), .clk(clk)); switchbank_int sw1(.clk(clk), .switches(16'(switches)), .enter_key(enter_key), .ack(ackx) , .interrupt(switch_interrupt),.data_reg(switch_in)); mammal m1( .clk(clk), .data_in(data_in), .data_out(data_out), .address(address), .memwt(memwt),.INT(INT), .intack(intack)); //===============IRQ's============== always_comb begin irq0 = 1'b0; irq1 = 1'b0; irq2 = switch_interrupt; irq3 = 1'b0; irq4 = 1'b0; irq5 = 1'b0; irq6 = 1'b0; irq7 = 1'b0; end //we assume that the devices hold their irq until being serviced by cpu assign INT = irq0 | irq1 | irq2 | irq3 | irq4 | irq5 | irq6 | irq7; //====multiplexer for cpu input====== always_comb begin ackx = 0; if (intack == 0) begin ackx = 0; if ( (BEGINMEM<=address) && (address<=ENDMEM) ) data_in=memory[address]; else if (address==SWITCHBANK) begin ackx = 1; //with appropriate a0 resets the ready flag data_in = switch_in; //a0 will determine if we read data or status end else data_in=16'hf345; //last else to generate combinatorial circuit. end else //intack = 1 begin if (irq0) //highest priority interrupt is irq0 data_in = 16'h0; else if (irq1) data_in = 16'h1; else if (irq2) data_in = 16'h2; else if (irq3) data_in = 16'h3; else if (irq4) data_in = 16'h4; else if (irq5) data_in = 16'h5; else if (irq6) data_in = 16'h6; else // irq7 data_in = 16'h7; end end //=====multiplexer for cpu output=========== always_ff @(posedge clk) //data output port of the cpu if (memwt) if ( (BEGINMEM<=address) && (address<=ENDMEM) ) memory[address]<=data_out; else if ( SEVENSEG==address ) ss7_out<=data_out; initial begin switch_interrupt =0; ss7_out =16'b0; $readmemh("ram.dat", memory); end endmodule
A simple assembly language program which manages the interrupt signal is given below: You can use this program as a test to see whether everything in hardware works properly.
ldi 7 0x600 ldi 0 0x7f2 ldi 1 isr st 0 1 sti loop jmp loop isr ldi 2 0x900 ld 2 2 ldi 3 0xb00 st 3 2 sti iret