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
- Mammal 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 [3: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'h1ff,
SWITCHBANK = 12'h900,
SEVENSEG = 12'hb00;
//====memory chip==============
logic [15:0] memory [0:511];
//=====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 (.din(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 0x1E0
ldi 0 0x1f2
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