feat(confreg): add interrupt control
This commit is contained in:
@@ -351,6 +351,68 @@ end
|
|||||||
|
|
||||||
//-------------------------------{int_ctrl}begin----------------------------//
|
//-------------------------------{int_ctrl}begin----------------------------//
|
||||||
//add your code
|
//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-----------------------------//
|
//--------------------------------{int_ctrl}end-----------------------------//
|
||||||
|
|
||||||
|
|||||||
67
rtl/ip/confreg/int_ctrl.v
Normal file
67
rtl/ip/confreg/int_ctrl.v
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user