Forum Discussion
Hi, I need some advice for implementing MSI MaskRegister for my lattice Board which doesn't support MSI -X features(include Mask Register) I have implemented the MSI Interrupt and test it under Linux 1 months ago for my Lattice PCI Express IP Core with Wishbone interface for slaves. But now I am facing a problem to integrated a Mask register to facilitate the driver development. Below is what I have implemented . Could anybody give me a feedback to make sure I am on the rigth way? Notice: Lattice ECP3 just support up to 8 MSI Interrupts. module msi_maskregister( clk_i, rst_i, cyc_i, stb_i, adr_i, we_i, dat_i, dat_o, ack_o, msi ); parameter is = 8; // Number of interrupt sources // // Inputs & outputs // // 8bit WISHBONE bus slave interface input clk_i; // clock input rst_i; // reset (asynchronous active low) input cyc_i; // cycle input stb_i; // strobe (cycle and strobe are the same signal) input [ 2:1] adr_i; // address input we_i; // write enable input [ 7:0] dat_i; // data output output [ 7:0] dat_o; // data input output ack_o; // normal bus termination // Interrupt sources input [is:1] msi; // interrupt request inputs // // Module body // reg [is:1] pol, edgen, mask; // register bank reg [is:1] lirq, dirq; // latched irqs, delayed latched irqs // // latch interrupt inputs always @(posedge clk_i) lirq <=# 1 msi; // // generate delayed latched irqs always @(posedge clk_i) dirq <=# 1 lirq; // // generate actual triggers function trigger; input edgen, pol, lirq, dirq; reg edge_irq, level_irq; begin edge_irq = pol ? (lirq & ~dirq) : (dirq & ~lirq); ///////// Masking level_irq = pol ? lirq : ~lirq; trigger = edgen ? edge_irq : level_irq; end endfunction reg [is:1] irq_event; integer n; always @(posedge clk_i) for(n=1; n<=is; n=n+1) irq_event[n] <=# 1 trigger(edgen[n], pol[n], lirq[n], dirq[n]); // // generate wishbone register bank writes wire wb_acc = cyc_i & stb_i; // WISHBONE access wire wb_wr = wb_acc & we_i; // WISHBONE write access always @(posedge clk_i or negedge rst_i) if (~rst_i) begin pol <=# 1 {{is}{1'b0}}; // clear polarity register edgen <=# 1 {{is}{1'b0}}; // clear edge enable register mask <=# 1 {{is}{1'b1}}; // mask all interrupts end // 0x00: EdgeEnable Register // 0x01: PolarityRegister // 0x02: MaskRegister else if(wb_wr) // wishbone write cycle?? case (adr_i) // synopsys full_case parallel_case 2'b00: edgen <=# 1 dat_i[is-1:0]; // EDGE-ENABLE register 2'b01: pol <=# 1 dat_i[is-1:0]; // POLARITY register 2'b10: mask <=# 1 dat_i[is-1:0]; // MASK register endcase // // generate dat_o reg [7:0] dat_o; always @(posedge clk_i) case (adr_i) // synopsys full_case parallel_case 2'b00: dat_o <=# 1 { {{8-is}{1'b0}}, edgen}; //{ {{8-is}{1'b0}}, edgen} 2'b01: dat_o <=# 1 { {{8-is}{1'b0}}, pol}; 2'b10: dat_o <=# 1 { {{8-is}{1'b0}}, mask}; endcase // // generate ack_o reg ack_o; always @(posedge clk_i) ack_o <=# 1 wb_acc & !ack_o; endmodule