From 4217ce2f5bbc6a08236327819739dd43182310b7 Mon Sep 17 00:00:00 2001 From: FallenSigh Date: Sun, 12 Apr 2026 22:25:31 +0800 Subject: [PATCH] feat(confreg): add interrupt control --- rtl/ip/confreg/confreg.v | 62 ++++++++++++++++++++++++++++++++++++ rtl/ip/confreg/int_ctrl.v | 67 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 rtl/ip/confreg/int_ctrl.v diff --git a/rtl/ip/confreg/confreg.v b/rtl/ip/confreg/confreg.v index 6a10d8b..7592f2b 100644 --- a/rtl/ip/confreg/confreg.v +++ b/rtl/ip/confreg/confreg.v @@ -351,6 +351,68 @@ end //-------------------------------{int_ctrl}begin----------------------------// //add your code +wire [31:0] int_in; +wire [31:0] int_out; + +wire write_int_en = w_enter & (buf_addr[15:0] == (`CONFREG_INT_ADDR + 16'h0)); +wire write_int_edge = w_enter & (buf_addr[15:0] == (`CONFREG_INT_ADDR + 16'h4)); +wire write_int_pol = w_enter & (buf_addr[15:0] == (`CONFREG_INT_ADDR + 16'h8)); +wire write_int_clr = w_enter & (buf_addr[15:0] == (`CONFREG_INT_ADDR + 16'hc)); +wire write_int_set = w_enter & (buf_addr[15:0] == (`CONFREG_INT_ADDR + 16'h10)); + +always @(posedge aclk) begin + if (!aresetn) begin + confreg_int_en <= 32'h0; + confreg_int_edge <= 32'h0; + confreg_int_pol <= 32'h0; + end else begin + if (write_int_en) confreg_int_en <= s_wdata; + if (write_int_edge) confreg_int_edge <= s_wdata; + if (write_int_pol) confreg_int_pol <= s_wdata; + end +end + +always @(posedge aclk) begin + if (!aresetn) begin + confreg_int_clr <= 32'h0; + confreg_int_set <= 32'h0; + end else begin + confreg_int_clr <= write_int_clr ? s_wdata : 32'h0; + confreg_int_set <= write_int_set ? s_wdata : 32'h0; + end +end + +assign int_in = {27'b0, timer_int, touch_btn_data}; + +int_ctrl u_int_ctrl ( + .clk (aclk), + .resetn (aresetn), + .int_en (confreg_int_en), + .int_edge (confreg_int_edge), + .int_pol (confreg_int_pol), + .int_in (int_in), + .int_clr (confreg_int_clr), + .int_set (confreg_int_set), + .int_out (int_out) +); + +assign confreg_int_state = int_out; + +// int_out 进行或操作,再经过延迟打拍处理 +reg int_out_or_q1; +reg int_out_or_q2; + +always @(posedge aclk) begin + if (!aresetn) begin + int_out_or_q1 <= 1'b0; + int_out_or_q2 <= 1'b0; + end else begin + int_out_or_q1 <= |int_out; + int_out_or_q2 <= int_out_or_q1; + end +end + +assign confreg_int = int_out_or_q2; //--------------------------------{int_ctrl}end-----------------------------// diff --git a/rtl/ip/confreg/int_ctrl.v b/rtl/ip/confreg/int_ctrl.v new file mode 100644 index 0000000..62ef033 --- /dev/null +++ b/rtl/ip/confreg/int_ctrl.v @@ -0,0 +1,67 @@ +module int_ctrl ( + input wire clk, + input wire resetn, + input wire [31:0] int_en, // 中断使能:1有效 + input wire [31:0] int_edge, // 触发方式:1边沿触发,0电平触发 + input wire [31:0] int_pol, // 极性选择:电平(1高/0低),边沿(1上升沿/0下降沿) + input wire [31:0] int_in, // 外部输入中断信号 + input wire [31:0] int_clr, // 软件中断清除(针对边沿触发) + input wire [31:0] int_set, // 软件中断置位(针对边沿触发) + output wire [31:0] int_out // 最终输出到处理器的高电平有效中断信号 +); + + // 寄存输入信号以检测边沿 + reg [31:0] int_in_d1; + always @(posedge clk or negedge resetn) begin + if (!resetn) begin + int_in_d1 <= 32'b0; + end else begin + int_in_d1 <= int_in; + end + end + + // 生成上升沿和下降沿信号 + wire [31:0] rising_edge = int_in & ~int_in_d1; + wire [31:0] falling_edge = ~int_in & int_in_d1; + + // 边沿触发状态维护寄存器 + reg [31:0] edge_int_state; + integer i; + always @(posedge clk or negedge resetn) begin + if (!resetn) begin + edge_int_state <= 32'b0; + end else begin + for (i = 0; i < 32; i = i + 1) begin + // 清除操作优先级最高(按照基础SoC惯例,写clr信号清零) + if (int_clr[i]) begin + edge_int_state[i] <= 1'b0; + end + // 软件置位操作 + else if (int_set[i]) begin + edge_int_state[i] <= 1'b1; + end + // 硬件检测到有效边沿并锁存 + else if (int_edge[i]) begin + if (int_pol[i] && rising_edge[i]) begin + edge_int_state[i] <= 1'b1; // 上升沿触发 + end else if (!int_pol[i] && falling_edge[i]) begin + edge_int_state[i] <= 1'b1; // 下降沿触发 + end + end + end + end + end + + // 电平触发状态评估 + // 如果极性配置为1(高电平触发),则 int_in 为1时有效 + // 如果极性配置为0(低电平触发),则 int_in 为0时有效 + wire [31:0] level_int_state; + assign level_int_state = (int_in & int_pol) | (~int_in & ~int_pol); + + // 结合 edge/level 选择,并用 en 屏蔽 + assign int_out = int_en & ( + (int_edge & edge_int_state) | + (~int_edge & level_int_state) + ); + +endmodule \ No newline at end of file