diff --git a/hw/efinix_fpga/src/byte_sel_register.sv b/hw/efinix_fpga/src/byte_sel_register.sv new file mode 100644 index 0000000..7ea3e10 --- /dev/null +++ b/hw/efinix_fpga/src/byte_sel_register.sv @@ -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 \ No newline at end of file diff --git a/hw/efinix_fpga/src/interrupt_controller.sv b/hw/efinix_fpga/src/interrupt_controller.sv index 4e00957..f5107bf 100644 --- a/hw/efinix_fpga/src/interrupt_controller.sv +++ b/hw/efinix_fpga/src/interrupt_controller.sv @@ -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 diff --git a/hw/efinix_fpga/src/super6502.sv b/hw/efinix_fpga/src/super6502.sv index 66fd0fd..f296019 100644 --- a/hw/efinix_fpga/src/super6502.sv +++ b/hw/efinix_fpga/src/super6502.sv @@ -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) ); diff --git a/hw/efinix_fpga/super6502.xml b/hw/efinix_fpga/super6502.xml index 013bb59..709d4f1 100644 --- a/hw/efinix_fpga/super6502.xml +++ b/hw/efinix_fpga/super6502.xml @@ -1,5 +1,5 @@ - + @@ -20,6 +20,7 @@ +