1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-17 20:02:53 +08:00

Simplifying module

-Interrupt should be kept separate from GPIO (use PIC)
This commit is contained in:
Andreas Olofsson 2016-02-26 19:06:38 -05:00
parent 8cb368027c
commit 9aed3f19d2
3 changed files with 29 additions and 111 deletions

11
gpio/README.md Normal file
View File

@ -0,0 +1,11 @@
GPIO
=======
A General Purpose IO module with all pins individually configurable as inputs or outputs. Output pins are controlled by writing to the ODATA register. Inputs are sampled by reading the IDATA register. Inputs can be configured to trigger interupts.

View File

@ -1,16 +1,15 @@
//######################################################################### //#########################################################################
//# GPIO (Supports up to 32 GPIO pins) //# GPIO
//# -each pin can be an output or input //# -each pin can be an output or input
//# -level and edge interrupts supported on every input pin
//######################################################################### //#########################################################################
`include "gpio_regmap.v" `include "gpio_regmap.v"
module gpio(/*AUTOARG*/ module gpio(/*AUTOARG*/
// Outputs // Outputs
reg_rdata, gpio_out, gpio_en, gpio_irq, gpio_ilat, reg_rdata, io_out, io_en, gpio_irq, gpio_data,
// Inputs // Inputs
nreset, clk, reg_access, reg_packet, gpio_in nreset, clk, reg_access, reg_packet, io_in
); );
//################################################################## //##################################################################
@ -32,14 +31,13 @@ module gpio(/*AUTOARG*/
output [31:0] reg_rdata; // readback data output [31:0] reg_rdata; // readback data
//IO signals //IO signals
output [N-1:0] gpio_out; // data to drive to IO pins output [N-1:0] io_out; // data to drive to IO pins
output [N-1:0] gpio_en; // tristate enables for IO pins output [N-1:0] io_en; // tristate enables for IO pins
input [N-1:0] gpio_in; // data from IO pins input [N-1:0] io_in; // data from IO pins
//global interrupt //global interrupt
output gpio_irq; // or of all interrupts output gpio_irq; // change detected on an input
output [31:0] gpio_ilat; // individual interrupt outputs output [N-1:0] gpio_data; // individual interrupt outputs
//################################################################## //##################################################################
//# BODY //# BODY
@ -49,16 +47,9 @@ module gpio(/*AUTOARG*/
reg [N-1:0] odata_reg; reg [N-1:0] odata_reg;
reg [N-1:0] oen_reg; reg [N-1:0] oen_reg;
reg [N-1:0] idata_reg; reg [N-1:0] idata_reg;
reg [N-1:0] itype_reg;
reg [N-1:0] ipol_reg;
reg [N-1:0] imask_reg;
reg [N-1:0] ilat_reg;
reg [N-1:0] gpio_reg;
reg [AW-1:0] reg_rdata; reg [AW-1:0] reg_rdata;
//nets //nets
reg [N-1:0] ilat_in;
reg [N-1:0] ilat_event;
wire [N-1:0] gpio_sync; wire [N-1:0] gpio_sync;
wire [N-1:0] event_posedge; wire [N-1:0] event_posedge;
wire [N-1:0] event_negedge; wire [N-1:0] event_negedge;
@ -97,26 +88,15 @@ module gpio(/*AUTOARG*/
.srcaddr_in (srcaddr_in[AW-1:0]), .srcaddr_in (srcaddr_in[AW-1:0]),
.data_in (data_in[AW-1:0])); .data_in (data_in[AW-1:0]));
assign reg_write = reg_access & write_in;
assign reg_read = reg_access & ~write_in;
assign gpio_match = reg_access & assign odata_write = reg_write & (dstaddr_in[7:2]==`GPIO_ODATA);
(dstaddr_in[10:8]==ID); assign odataand_write = reg_write & (dstaddr_in[7:2]==`GPIO_ODATAAND);
assign odataorr_write = reg_write & (dstaddr_in[7:2]==`GPIO_ODATAORR);
assign gpio_write = gpio_match & write_in; assign odataxor_write = reg_write & (dstaddr_in[7:2]==`GPIO_ODATAXOR);
assign gpio_read = gpio_match & ~write_in; assign oen_write = reg_write & (dstaddr_in[7:2]==`GPIO_OEN);
assign idata_write = reg_write & (dstaddr_in[7:2]==`GPIO_IDATA);
assign odata_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ODATA);
assign odataand_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ODATAAND);
assign odataorr_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ODATAORR);
assign odataxor_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ODATAXOR);
assign oen_write = gpio_write & (dstaddr_in[7:2]==`GPIO_OEN);
assign idata_write = gpio_write & (dstaddr_in[7:2]==`GPIO_IDATA);
assign itype_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ITYPE);
assign ipol_write = gpio_write & (dstaddr_in[7:2]==`GPIO_IPOL);
assign imask_write = gpio_write & (dstaddr_in[7:2]==`GPIO_IMASK);
assign imaskand_write = gpio_write & (dstaddr_in[7:2]==`GPIO_IMASKAND);
assign imaskorr_write = gpio_write & (dstaddr_in[7:2]==`GPIO_IMASKORR);
assign ilat_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ILAT);
assign ilatand_write = gpio_write & (dstaddr_in[7:2]==`GPIO_ILATAND);
//################################ //################################
//# OUTPUT CONTROL REGISTERS //# OUTPUT CONTROL REGISTERS
@ -148,79 +128,14 @@ module gpio(/*AUTOARG*/
always @ (posedge clk) always @ (posedge clk)
idata_reg[N-1:0] <= gpio_sync[N-1:0]; idata_reg[N-1:0] <= gpio_sync[N-1:0];
//ITYPE
//0=level
//1=edge
always @ (posedge clk)
if(itype_write)
itype_reg[N-1:0] <= data_in[N-1:0];
//IPOLARITY
//0=positive
//1=negative
always @ (posedge clk)
if(ipol_write)
ipol_reg[N-1:0] <= data_in[N-1:0];
//IMASK
always @ (posedge clk)
if(imask_write)
imask_reg[N-1:0] <= data_in[N-1:0];
else if(imaskand_write)
imask_reg[N-1:0] <= imask_reg[N-1:0] & data_in[N-1:0];
else if(imaskorr_write)
imask_reg[N-1:0] <= imask_reg[N-1:0] | data_in[N-1:0];
//ILAT
always @ (posedge clk or negedge nreset)
if(~nreset)
ilat_reg[N-1:0] <= 'b0;
else
ilat_reg[N-1:0] <= ilat_in[N-1:0];
//################################
//# INTERRUPT CONTROL
//################################
//ILAT
always @*
for(i=0;i<N;i=i+1)
ilat_in[i] =(ilat_write & data_in[i]) | // ilat set
(ilat_reg[i] & ~(ilatand_write & ~data_in[i]))|// ilat clear
(ilat_event[i]); // event
//shadow
always @ (posedge clk)
gpio_reg[N-1:0] <= gpio_sync[N-1:0];
//events
assign event_posedge[N-1:0] = gpio_sync[N-1:0] & ~gpio_reg[N-1:0];
assign event_negedge[N-1:0] = ~gpio_sync[N-1:0] & gpio_reg[N-1:0];
always @*
for(j=0;j<N;j=j+1)
ilat_event[j] = (~itype_reg[j] & ~ipol_reg[j] & gpio_sync[j]) |
(~itype_reg[j] & ipol_reg[j] & ~gpio_sync[j]) |
(itype_reg[j] & ~ipol_reg[j] & event_posedge[j]) |
(itype_reg[j] & ipol_reg[j] & event_negedge[j]);
//global interrupt output
assign gpio_irq = |ilat_reg[N-1:0];
//################################ //################################
//# READBACK //# READBACK
//################################ //################################
always @ (posedge clk) always @ (posedge clk)
if(gpio_read) if(reg_read)
case(dstaddr_in[7:2]) case(dstaddr_in[7:2])
`GPIO_OEN : reg_rdata[31:0] <= oen_reg[N-1:0]; `GPIO_OEN : reg_rdata[31:0] <= oen_reg[N-1:0];
`GPIO_IDATA : reg_rdata[31:0] <= idata_reg[N-1:0]; `GPIO_IDATA : reg_rdata[31:0] <= idata_reg[N-1:0];
`GPIO_ITYPE : reg_rdata[31:0] <= itype_reg[N-1:0];
`GPIO_IPOL : reg_rdata[31:0] <= ipol_reg[N-1:0];
`GPIO_IMASK : reg_rdata[31:0] <= imask_reg[N-1:0];
`GPIO_ILAT : reg_rdata[31:0] <= ilat_reg[N-1:0];
default : reg_rdata[AW-1:0] <='b0; default : reg_rdata[AW-1:0] <='b0;
endcase // case (dstaddr_in[7:2]) endcase // case (dstaddr_in[7:2])

View File

@ -7,13 +7,5 @@
`define GPIO_ODATAXOR 6'h3 `define GPIO_ODATAXOR 6'h3
`define GPIO_OEN 6'h4 `define GPIO_OEN 6'h4
`define GPIO_IDATA 6'h5 `define GPIO_IDATA 6'h5
`define GPIO_ITYPE 6'h6
`define GPIO_IPOL 6'h7
`define GPIO_IMASK 6'h8
`define GPIO_IMASKAND 6'h9
`define GPIO_IMASKORR 6'h10
`define GPIO_ILAT 6'h11
`define GPIO_ILATAND 6'h12
`endif `endif