Add beginnings of interrupt controller
This commit is contained in:
25
hw/efinix_fpga/src/byte_sel_register.sv
Normal file
25
hw/efinix_fpga/src/byte_sel_register.sv
Normal file
@@ -0,0 +1,25 @@
|
||||
module byte_sel_register
|
||||
#(
|
||||
parameter DATA_WIDTH = 8,
|
||||
parameter ADDR_WIDTH = 32
|
||||
)(
|
||||
input i_clk,
|
||||
input i_write,
|
||||
input [$clog2(ADDR_WIDTH)-1:0] i_byte_sel,
|
||||
input [DATA_WIDTH-1:0] i_data,
|
||||
output [DATA_WIDTH-1:0] o_data,
|
||||
output [DATA_WIDTH*ADDR_WIDTH-1:0] o_full_data
|
||||
);
|
||||
|
||||
logic [DATA_WIDTH*ADDR_WIDTH-1:0] r_data;
|
||||
|
||||
assign o_data = r_data[DATA_WIDTH*i_byte_sel +: DATA_WIDTH];
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
r_data <= r_data;
|
||||
if (i_write) begin
|
||||
r_data[DATA_WIDTH*i_byte_sel +: DATA_WIDTH] <= i_data;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -4,26 +4,72 @@ module interrupt_controller
|
||||
input reset,
|
||||
input [7:0] i_data,
|
||||
output logic [7:0] o_data,
|
||||
input addr,
|
||||
input cs,
|
||||
input rwb,
|
||||
|
||||
output logic irqb_master,
|
||||
|
||||
input irqb0, irqb1, irqb2, irqb3,
|
||||
input irqb4, irqb5, irqb6, irqb7
|
||||
input [255:0] int_in,
|
||||
output logic int_out
|
||||
);
|
||||
|
||||
logic [7:0] w_enable_data;
|
||||
logic [255:0] w_enable_full_data;
|
||||
|
||||
//All of the inputs are low level triggered.
|
||||
logic [7:0] irqbv;
|
||||
assign irqbv = {irqb0, irqb1, irqb2, irqb3, irqb4, irqb5, irqb6, irqb7};
|
||||
logic [4:0] w_byte_sel;
|
||||
|
||||
always @(posedge clk) begin
|
||||
o_data <= irqbv;
|
||||
irqb_master = &irqbv;
|
||||
logic [7:0] irq_val;
|
||||
|
||||
if (cs & ~rwb) begin
|
||||
o_data <= o_data | i_data;
|
||||
byte_sel_register #(
|
||||
.DATA_WIDTH(8),
|
||||
.ADDR_WIDTH(32)
|
||||
) reg_enable (
|
||||
.i_clk(clk),
|
||||
.i_write(w_enable_write),
|
||||
.i_byte_sel(w_byte_sel),
|
||||
.i_data(i_data),
|
||||
.o_data(w_enable_data),
|
||||
.o_full_data(w_enable_full_data)
|
||||
);
|
||||
|
||||
logic [255:0] int_masked;
|
||||
assign int_masked = int_in & w_enable_full_data;
|
||||
|
||||
|
||||
logic [7:0] w_type_data;
|
||||
logic [255:0] w_type_full_data;
|
||||
|
||||
byte_sel_register #(
|
||||
.DATA_WIDTH(8),
|
||||
.ADDR_WIDTH(32)
|
||||
) reg_type (
|
||||
.i_clk(clk),
|
||||
.i_write(w_type_write),
|
||||
.i_byte_sel(w_byte_sel),
|
||||
.i_data(i_data),
|
||||
.o_data(w_type_data),
|
||||
.o_full_data(w_type_full_data)
|
||||
);
|
||||
|
||||
logic w_eoi;
|
||||
|
||||
logic [255:0] r_int, r_int_next;
|
||||
|
||||
always_comb begin
|
||||
r_int_next = (~r_int | w_type_full_data) & int_masked;
|
||||
if (w_eoi) begin
|
||||
r_int_next[irq_val] = 0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
r_int <= r_int_next;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
for (int i = 255; i == 0; i--) begin
|
||||
if (r_int[i] == 1) begin
|
||||
irq_val = i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -267,16 +267,7 @@ interrupt_controller u_interrupt_controller(
|
||||
.i_data(cpu_data_in),
|
||||
.o_data(w_irq_data_out),
|
||||
.cs(w_irq_cs),
|
||||
.rwb(cpu_rwb),
|
||||
.irqb_master(cpu_irqb),
|
||||
.irqb0(w_timer_irqb),
|
||||
.irqb1('1),
|
||||
.irqb2('1),
|
||||
.irqb3('1),
|
||||
.irqb4('1),
|
||||
.irqb5('1),
|
||||
.irqb6('1),
|
||||
.irqb7('1)
|
||||
.rwb(cpu_rwb)
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user