Annett
Senior
Joined: 30 Mar 2017 00:55 Posts: 137
|
module interrupt_controller(IRQ,CLK16M,FC,ADDR,DIN,nAS,nUDS,nLDS,RW,nRESET, RS_CTRL,RS_PCH,RS_PCL,RS_MH,RS_ML, IPL, DOUT, DTEN, DTA); input wire [19:0] IRQ; input wire CLK16M; input wire [2:0] FC; input wire [23:1] ADDR; input wire [15:0] DIN; input wire nAS, nUDS, nLDS, RW, nRESET, RS_CTRL, RS_PCH, RS_PCL, RS_MH, RS_ML; output wire [2:0] IPL; output wire [15:0] DOUT; output wire DTEN,DTA; //output wire T1,T2,T3,T4;
reg RST;
reg [4:0] COUNTER; //IRQ scan counter reg [4:0] DRCNT; //AUTO-EOI delay counter reg [31:0] IDC; //IRQ scan decoder output lines reg [19:0] MASK; //IRQ mask reg reg IPD,IPLF, DRS; reg [4:0] IRQ_NUM; //IRQ num buffer register
wire XDS, WDS, WWSTB, RWSTB, MHWSTB, MLWSTB, MHRSTB, MLRSTB, PHRSTB, PLRSTB, CHWSTB; wire CLWSTB, FSCLK, SETCNT, IACK, XFLAG,DRCLK;
wire [19:0] CLR; wire [19:0] POLL; wire [19:0] FLAG; wire [7:0] VECTOR;
always@(negedge CLK16M) RST <= (~nRESET); //synchronize reset pulse to system clock
assign XDS = (~nUDS) | (~nLDS); assign WDS = (~nUDS) & (~nLDS);
assign IACK = (ADDR[23:8] == 16'hFFFF) & (~nAS) & RW & (~nLDS) & (ADDR[3] & ADDR[2] & (~ADDR[1])) & (FC[2] & FC[1] & FC[0]); assign WWSTB = (~RW) & WDS; //write_word strobe assign RWSTB = RW & WDS; //read_word strobe assign MHWSTB = RS_MH & WWSTB; //mask reg H write strobe assign MLWSTB = RS_ML & WWSTB; //mask reg L write strobe assign MHRSTB = RS_MH & RWSTB; //mask reg H read strobe assign MLRSTB = RS_ML & RWSTB; //mask reg L read strobe assign PHRSTB = RS_PCH & RWSTB; //polling reg H read strobe assign PLRSTB = RS_PCL & RWSTB; //polling reg L read strobe assign CHWSTB = RS_PCH & WWSTB; //flag clr reg H write strobe assign CLWSTB = RS_PCL & WWSTB; //flag clr reg L write strobe
assign CLR[15:0] = DIN[15:0] & {16{CLWSTB}}; // generate flag clear strobes assign CLR[19:16] = DIN[3:0] & {4{CHWSTB}};
//load IRQ mask register always@(negedge MHWSTB or posedge RST) begin if (RST) MASK[19:16] <= 4'd0; else MASK[19:16] <= DIN[3:0]; end always@(negedge MLWSTB or posedge RST) begin if (RST) MASK[15:0] <= 16'd0; else MASK[15:0] <= DIN[15:0]; end
//generate output data assign DOUT[15:8] = (POLL[15:8]&{8{PLRSTB}}) | (MASK[15:8]&{8{MLRSTB}}); assign DOUT[7:0] = (POLL[7:0] &{8{PLRSTB}}) | (POLL[19:16]&{4{PHRSTB}}) | (MASK[7:0]&{8{MLRSTB}}) | (MASK[19:16]&{4{MHRSTB}}) | (VECTOR[7:0]&{8{IACK}});
//sys data bus drive enable strobe (read cycle) assign DTEN = (RW & XDS & (RS_CTRL | RS_PCH | RS_PCL | RS_MH | RS_ML)) | IACK;
//generate DTACK signal assign DTA = (XDS & (RS_CTRL | RS_PCH | RS_PCL | RS_MH | RS_ML)) | IACK;
//generate IPL code for CPU assign IPL[0] = 1; assign IPL[1] = ~IPLF; assign IPL[2] = ~IPLF;
//===========================================================
IRQ_channel IFLAG_19 (.IRQ(IRQ[19]),.CLR(CLR[19]),.RST(RST),.IACK(IACK),.IDC(IDC[19]),.MASK(MASK[19]), .POLL(POLL[19]),.FLAG(FLAG[19])); IRQ_channel IFLAG_18 (.IRQ(IRQ[18]),.CLR(CLR[18]),.RST(RST),.IACK(IACK),.IDC(IDC[18]),.MASK(MASK[18]), .POLL(POLL[18]),.FLAG(FLAG[18])); IRQ_channel IFLAG_17 (.IRQ(IRQ[17]),.CLR(CLR[17]),.RST(RST),.IACK(IACK),.IDC(IDC[17]),.MASK(MASK[17]), .POLL(POLL[17]),.FLAG(FLAG[17])); IRQ_channel IFLAG_16 (.IRQ(IRQ[16]),.CLR(CLR[16]),.RST(RST),.IACK(IACK),.IDC(IDC[16]),.MASK(MASK[16]), .POLL(POLL[16]),.FLAG(FLAG[16])); IRQ_channel IFLAG_15 (.IRQ(IRQ[15]),.CLR(CLR[15]),.RST(RST),.IACK(IACK),.IDC(IDC[15]),.MASK(MASK[15]), .POLL(POLL[15]),.FLAG(FLAG[15])); IRQ_channel IFLAG_14 (.IRQ(IRQ[14]),.CLR(CLR[14]),.RST(RST),.IACK(IACK),.IDC(IDC[14]),.MASK(MASK[14]), .POLL(POLL[14]),.FLAG(FLAG[14])); IRQ_channel IFLAG_13 (.IRQ(IRQ[13]),.CLR(CLR[13]),.RST(RST),.IACK(IACK),.IDC(IDC[13]),.MASK(MASK[13]), .POLL(POLL[13]),.FLAG(FLAG[13])); IRQ_channel IFLAG_12 (.IRQ(IRQ[12]),.CLR(CLR[12]),.RST(RST),.IACK(IACK),.IDC(IDC[12]),.MASK(MASK[12]), .POLL(POLL[12]),.FLAG(FLAG[12])); IRQ_channel IFLAG_11 (.IRQ(IRQ[11]),.CLR(CLR[11]),.RST(RST),.IACK(IACK),.IDC(IDC[11]),.MASK(MASK[11]), .POLL(POLL[11]),.FLAG(FLAG[11])); IRQ_channel IFLAG_10 (.IRQ(IRQ[10]),.CLR(CLR[10]),.RST(RST),.IACK(IACK),.IDC(IDC[10]),.MASK(MASK[10]), .POLL(POLL[10]),.FLAG(FLAG[10])); IRQ_channel IFLAG_9 (.IRQ(IRQ[9]),.CLR(CLR[9]),.RST(RST),.IACK(IACK),.IDC(IDC[9]),.MASK(MASK[9]), .POLL(POLL[9]),.FLAG(FLAG[9])); IRQ_channel IFLAG_8 (.IRQ(IRQ[8]),.CLR(CLR[8]),.RST(RST),.IACK(IACK),.IDC(IDC[8]),.MASK(MASK[8]), .POLL(POLL[8]),.FLAG(FLAG[8])); IRQ_channel IFLAG_7 (.IRQ(IRQ[7]),.CLR(CLR[7]),.RST(RST),.IACK(IACK),.IDC(IDC[7]),.MASK(MASK[7]), .POLL(POLL[7]),.FLAG(FLAG[7])); IRQ_channel IFLAG_6 (.IRQ(IRQ[6]),.CLR(CLR[6]),.RST(RST),.IACK(IACK),.IDC(IDC[6]),.MASK(MASK[6]), .POLL(POLL[6]),.FLAG(FLAG[6])); IRQ_channel IFLAG_5 (.IRQ(IRQ[5]),.CLR(CLR[5]),.RST(RST),.IACK(IACK),.IDC(IDC[5]),.MASK(MASK[5]), .POLL(POLL[5]),.FLAG(FLAG[5])); IRQ_channel IFLAG_4 (.IRQ(IRQ[4]),.CLR(CLR[4]),.RST(RST),.IACK(IACK),.IDC(IDC[4]),.MASK(MASK[4]), .POLL(POLL[4]),.FLAG(FLAG[4])); IRQ_channel IFLAG_3 (.IRQ(IRQ[3]),.CLR(CLR[3]),.RST(RST),.IACK(IACK),.IDC(IDC[3]),.MASK(MASK[3]), .POLL(POLL[3]),.FLAG(FLAG[3])); IRQ_channel IFLAG_2 (.IRQ(IRQ[2]),.CLR(CLR[2]),.RST(RST),.IACK(IACK),.IDC(IDC[2]),.MASK(MASK[2]), .POLL(POLL[2]),.FLAG(FLAG[2])); IRQ_channel IFLAG_1 (.IRQ(IRQ[1]),.CLR(CLR[1]),.RST(RST),.IACK(IACK),.IDC(IDC[1]),.MASK(MASK[1]), .POLL(POLL[1]),.FLAG(FLAG[1])); IRQ_channel IFLAG_0 (.IRQ(IRQ[0]),.CLR(CLR[0]),.RST(RST),.IACK(IACK),.IDC(IDC[0]),.MASK(MASK[0]), .POLL(POLL[0]),.FLAG(FLAG[0]));
assign XFLAG = ~(FLAG == 20'h0);
always@(negedge FSCLK or posedge RST or posedge IACK) begin if (RST) IPLF <= 0; else begin if (IACK) IPLF <= 0; else IPLF <= XFLAG; end end
always@(posedge DRS or posedge IPLF or posedge RST) begin if (RST) IPD <= 0; else begin if (IPLF) IPD <=1; else IPD <= 0; end end
assign SETCNT = IACK | RST; assign FSCLK = CLK16M & (~IPD);
always@(posedge FSCLK or posedge SETCNT) begin if (SETCNT) COUNTER <= 5'd19; else begin if (COUNTER == 5'd19) COUNTER <= 5'd0; else COUNTER <= COUNTER + 1'd1; end end
always@(negedge FSCLK) IRQ_NUM <=COUNTER;
assign VECTOR[7:5] = 3'b010; //vector = 0x40 + irq_num assign VECTOR[4:0] = IRQ_NUM;
//auto EOI delay counter always@(negedge CLK16M or posedge RST) begin if (RST) DRS <=1; else begin if (IACK) DRS <= 0; else DRS <= (DRCNT == 5'h1F); end end
assign DRCLK = CLK16M & (~DRS); always@(posedge DRCLK or posedge IACK or posedge RST) begin if (RST) DRCNT <= 5'h1F; else begin if (IACK) DRCNT <= 5'h0; else DRCNT <= DRCNT + 1'h1; end end // assign T1 = FSCLK; // assign T2 = XFLAG; // assign T3 = IPD; // assign T4 = DRS; always@* begin case(COUNTER[4:0]) 5'h0: IDC=32'b00000000000000000000000000000001; 5'h1: IDC=32'b00000000000000000000000000000010; 5'h2: IDC=32'b00000000000000000000000000000100; 5'h3: IDC=32'b00000000000000000000000000001000; 5'h4: IDC=32'b00000000000000000000000000010000; 5'h5: IDC=32'b00000000000000000000000000100000; 5'h6: IDC=32'b00000000000000000000000001000000; 5'h7: IDC=32'b00000000000000000000000010000000; 5'h8: IDC=32'b00000000000000000000000100000000; 5'h9: IDC=32'b00000000000000000000001000000000; 5'hA: IDC=32'b00000000000000000000010000000000; 5'hB: IDC=32'b00000000000000000000100000000000; 5'hC: IDC=32'b00000000000000000001000000000000; 5'hD: IDC=32'b00000000000000000010000000000000; 5'hE: IDC=32'b00000000000000000100000000000000; 5'hF: IDC=32'b00000000000000001000000000000000; 5'h10: IDC=32'b00000000000000010000000000000000; 5'h11: IDC=32'b00000000000000100000000000000000; 5'h12: IDC=32'b00000000000001000000000000000000; 5'h13: IDC=32'b00000000000010000000000000000000; 5'h14: IDC=32'b00000000000100000000000000000000; 5'h15: IDC=32'b00000000001000000000000000000000; 5'h16: IDC=32'b00000000010000000000000000000000; 5'h17: IDC=32'b00000000100000000000000000000000; 5'h18: IDC=32'b00000001000000000000000000000000; 5'h19: IDC=32'b00000010000000000000000000000000; 5'h1A: IDC=32'b00000100000000000000000000000000; 5'h1B: IDC=32'b00001000000000000000000000000000; 5'h1C: IDC=32'b00010000000000000000000000000000; 5'h1D: IDC=32'b00100000000000000000000000000000; 5'h1E: IDC=32'b01000000000000000000000000000000; 5'h1F: IDC=32'b10000000000000000000000000000000; endcase end endmodule
//---------------------------------------------------------------------------------
module IRQ_channel(IRQ,CLR,RST,IACK,IDC,MASK, POLL,FLAG); input wire IRQ; input wire CLR; input wire RST; input wire IACK; input wire IDC; input wire MASK; output wire POLL; output wire FLAG;
reg IFLG; wire FCLR;
assign FCLR = RST | CLR | (IACK & IDC);
always@(posedge IRQ or posedge FCLR) begin if (FCLR) IFLG<= 0; else IFLG <= 1; end
assign POLL = IFLG; assign FLAG = IFLG & IDC & MASK; endmodule
|