From 2b248db94ffa1285284e5286248eaad59b403dda Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Wed, 15 Nov 2023 08:27:29 -0800 Subject: [PATCH] Add skeleton of interrupt controller --- hw/efinix_fpga/simulation/Makefile | 4 +- .../simulation/tbs/interrupt_controller_tb.sv | 93 +++++++++++++++++++ hw/efinix_fpga/src/byte_sel_register.sv | 12 ++- hw/efinix_fpga/src/interrupt_controller.sv | 55 ++++++++++- 4 files changed, 158 insertions(+), 6 deletions(-) create mode 100644 hw/efinix_fpga/simulation/tbs/interrupt_controller_tb.sv diff --git a/hw/efinix_fpga/simulation/Makefile b/hw/efinix_fpga/simulation/Makefile index 612d07f..bb818ae 100644 --- a/hw/efinix_fpga/simulation/Makefile +++ b/hw/efinix_fpga/simulation/Makefile @@ -9,6 +9,8 @@ TEST_PROGRAM_NAME?=loop_test TEST_FOLDER?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME) TEST_PROGRAM?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME)/$(TEST_PROGRAM_NAME).hex +STANDALONE_TB= interrupt_controller_tb mapper_code_tb + #TODO implement something like sources.list TOP_MODULE=sim_top @@ -29,7 +31,7 @@ sim: $(TARGET) full_sim: $(TARGET) $(SD_IMAGE) vvp -i $(TARGET) -fst -mapper_tb: $(SRCS) $(TBS) +$(STANDALONE_TB): $(SRCS) $(TBS) iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INC) $(SRCS) $(TBS) mapper_code_tb: $(SRCS) $(TBS) $(INIT_MEM) diff --git a/hw/efinix_fpga/simulation/tbs/interrupt_controller_tb.sv b/hw/efinix_fpga/simulation/tbs/interrupt_controller_tb.sv new file mode 100644 index 0000000..0f42817 --- /dev/null +++ b/hw/efinix_fpga/simulation/tbs/interrupt_controller_tb.sv @@ -0,0 +1,93 @@ +`timescale 1ns/1ps + +module interrupt_controller_tb(); + +logic r_clk_cpu; + +// clk_cpu +initial begin + r_clk_cpu <= '1; + forever begin + #125 r_clk_cpu <= ~r_clk_cpu; + end +end + +logic reset; +logic addr; +logic [7:0] i_data; +logic [7:0] o_data; +logic cs; +logic rwb; + +logic [255:0] int_in; +logic int_out; + +interrupt_controller u_interrupt_controller( + .clk(r_clk_cpu), + .reset(reset), + .i_data(i_data), + .o_data(o_data), + .addr(addr), + .cs(cs), + .rwb(rwb), + .int_in(int_in), + .int_out(int_out2) +); + +/* These should be shared */ +task write_reg(input logic [4:0] _addr, input logic [7:0] _data); + @(negedge r_clk_cpu); + cs <= '1; + addr <= _addr; + rwb <= '0; + i_data <= '1; + @(posedge r_clk_cpu); + i_data <= _data; + @(negedge r_clk_cpu); + cs <= '0; + rwb <= '1; +endtask + +task read_reg(input logic [2:0] _addr, output logic [7:0] _data); + @(negedge r_clk_cpu); + cs <= '1; + addr <= _addr; + rwb <= '1; + i_data <= '1; + @(posedge r_clk_cpu); + _data <= o_data; + @(negedge r_clk_cpu); + cs <= '0; + rwb <= '1; +endtask + +initial begin + repeat (5) @(posedge r_clk_cpu); + reset = 1; + cs = 0; + rwb = 1; + addr = '0; + i_data = '0; + int_in = '0; + repeat (5) @(posedge r_clk_cpu); + reset = 0; + repeat (5) @(posedge r_clk_cpu); + write_reg(0, 8'h10); + write_reg(1, 8'hff); + write_reg(0, 8'h20); + write_reg(1, 8'hff); + repeat (5) @(posedge r_clk_cpu); + int_in = 1; + @(posedge r_clk_cpu) + int_in = 0; + repeat (5) @(posedge r_clk_cpu); + $finish(); +end + +initial +begin + $dumpfile("interrupt_controller_tb.vcd"); + $dumpvars(0,interrupt_controller_tb); +end + +endmodule diff --git a/hw/efinix_fpga/src/byte_sel_register.sv b/hw/efinix_fpga/src/byte_sel_register.sv index 7ea3e10..c36c5c0 100644 --- a/hw/efinix_fpga/src/byte_sel_register.sv +++ b/hw/efinix_fpga/src/byte_sel_register.sv @@ -4,6 +4,7 @@ module byte_sel_register parameter ADDR_WIDTH = 32 )( input i_clk, + input i_reset, input i_write, input [$clog2(ADDR_WIDTH)-1:0] i_byte_sel, input [DATA_WIDTH-1:0] i_data, @@ -14,11 +15,16 @@ module byte_sel_register logic [DATA_WIDTH*ADDR_WIDTH-1:0] r_data; assign o_data = r_data[DATA_WIDTH*i_byte_sel +: DATA_WIDTH]; +assign o_full_data = r_data; 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; + if (i_reset) begin + r_data <= '0; + end else begin + r_data <= r_data; + if (i_write) begin + r_data[DATA_WIDTH*i_byte_sel +: DATA_WIDTH] <= i_data; + end end end diff --git a/hw/efinix_fpga/src/interrupt_controller.sv b/hw/efinix_fpga/src/interrupt_controller.sv index f5107bf..571619f 100644 --- a/hw/efinix_fpga/src/interrupt_controller.sv +++ b/hw/efinix_fpga/src/interrupt_controller.sv @@ -12,6 +12,7 @@ module interrupt_controller output logic int_out ); +logic w_enable_write; logic [7:0] w_enable_data; logic [255:0] w_enable_full_data; @@ -24,6 +25,7 @@ byte_sel_register #( .ADDR_WIDTH(32) ) reg_enable ( .i_clk(clk), + .i_reset(reset), .i_write(w_enable_write), .i_byte_sel(w_byte_sel), .i_data(i_data), @@ -31,10 +33,16 @@ byte_sel_register #( .o_full_data(w_enable_full_data) ); +logic we, re; + +assign we = cs & ~rwb; +assign re = cs & rwb; + logic [255:0] int_masked; assign int_masked = int_in & w_enable_full_data; +logic w_type_write; logic [7:0] w_type_data; logic [255:0] w_type_full_data; @@ -43,6 +51,7 @@ byte_sel_register #( .ADDR_WIDTH(32) ) reg_type ( .i_clk(clk), + .i_reset(reset), .i_write(w_type_write), .i_byte_sel(w_byte_sel), .i_data(i_data), @@ -50,6 +59,8 @@ byte_sel_register #( .o_full_data(w_type_full_data) ); +logic [7:0] cmd, cmd_next; + logic w_eoi; logic [255:0] r_int, r_int_next; @@ -59,10 +70,50 @@ always_comb begin if (w_eoi) begin r_int_next[irq_val] = 0; end + + if (addr == '0 && we) begin + cmd_next = i_data; + end else begin + cmd_next = cmd; + end + + + w_type_write = '0; + + if (addr == '1) begin + unique casez (cmd) + 8'h0?: begin + $display("Case 0 not handled"); + end + + 8'h1?: begin + w_enable_write = we; + w_byte_sel = cmd[3:0]; + o_data = w_enable_data; + end + + 8'h2?: begin + w_type_write = we; + w_byte_sel = cmd[3:0]; + o_data = w_type_data; + end + + 8'hff: begin + $display("Not handled"); + end + endcase + end + + int_out = |r_int; end -always_ff @(posedge clk) begin - r_int <= r_int_next; +always_ff @(negedge clk) begin + if (reset) begin + r_int <= '0; + end else begin + r_int <= r_int_next; + cmd <= cmd_next; + end end always_comb begin