Commit cbd7c464 authored by Andrey Filippov's avatar Andrey Filippov

added gpio393 module (ported from twelve_ios) to read/write GPIO pins,...

added gpio393 module (ported from twelve_ios) to read/write GPIO pins, selectively release control to other modules
parent 93e8aa42
......@@ -24,7 +24,7 @@
module rtc393 #(
parameter RTC_ADDR = 'h170, //TODO: assign valid address
parameter RTC_STATUS_REG_ADDR = 7, // address where status can be read out (currnelti just sequence # and alternating bit)
parameter RTC_STATUS_REG_ADDR = 7, // address where status can be read out (currently just sequence # and alternating bit)
parameter RTC_SEC_USEC_ADDR = 8, // address where seconds of the snapshot can be read (microseconds - next adderss)
parameter RTC_MASK = 'h3fc,
......
/*******************************************************************************
* Module: gpio393
* Date:2015-07-06
* Author: andrey
* Description: Control of the 10 GPIO signals of the 10393 board
* Converted from twelve_ios.v of teh x353 project (2005)
*
* Copyright (c) 2005-2015 Elphel, Inc.
* gpio393.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gpio393.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
// update to eliminate need for a shadow register
// each pair of data bits at write cycle control the data and enable in the following way:
// bit 1 bit 0 dibit enable data
// 0 0 0 - no change -
// 0 1 1 1 0
// 1 0 2 1 1
// 1 1 3 0 0
//Unified IO control for the 6 pins that are connected from the FPGA to the inter-board 16-pin connector
// those pins were controlled (in models 303, 313, 323 and earlier 333) by the control register, status was
// read through the status register.
// Now each pin will be controlled by 2 bits (data+enable), total 12 bits that will come from one of 4 sources
// selected by bits [13:12] of the new control word:
// 0 - use bits [11:0] of the control word
// 1 - use channel A (camsync)
// 2 - use channel B (tbd)
// 3 - use channel C (tbd)
// Updating logic
// global enable signals (disabled channel will not compete for per-biot access)
// next 4 enable signals are controlled by bit pairs (0X - don't change, 10 - disable, 11 - enable)
// bit [25:24] - enable software bits (contolled by bits [23:0] (on at powerup)
// bit [27:26] - enable chn. A
// bit [29:28] - enable chn. B
// bit [31:30] - enable chn. C
// Enabled bits will be priority encoded (C - highest, software - lowest)
module gpio393 #(
parameter GPIO_ADDR = 'h180, //TODO: assign valid address
parameter GPIO_MASK = 'h3fe,
parameter GPIO_STATUS_REG_ADDR = 'ha, // address where status can be read out (10 GPIO inputs)
parameter integer GPIO_DRIVE = 12,
parameter GPIO_IBUF_LOW_PWR = "TRUE",
parameter GPIO_IOSTANDARD = "DEFAULT", // power is 1.5V
parameter GPIO_SLEW = "SLOW",
parameter GPIO_SET_PINS = 0, // Set GPIO output state, give control for some bits to other modules
parameter GPIO_SET_STATUS = 1, // set status mode
parameter GPIO_N = 10, // number of GPIO bits to control
parameter GPIO_PORTEN = 24 // bit number to control port enables (up from this)
) (
input rst, // global reset
input mclk, // system clock
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
inout [GPIO_N-1:0] ext_pins, // GPIO pins (1.5V): assigned in 10389: [1:0] - i2c, [5:2] - gpio, [GPIO_N-1:6] - sync i/o
output [GPIO_N-1:0] io_pins, // values on the gpio pins (to use by other modules on ports A,B,C)
input [GPIO_N-1:0] da, // port A data
input [GPIO_N-1:0] da_en, // port A data enable
input [GPIO_N-1:0] db, // port A data
input [GPIO_N-1:0] db_en, // port A data enable
input [GPIO_N-1:0] dc, // port A data
input [GPIO_N-1:0] dc_en); // port A data enable
wire [GPIO_N-1:0] ds = 0; // "software" data (programmed by lower 24 bits)
wire [GPIO_N-1:0] ds_en = 0; // "software" data enable (programmed by lower 24 bits)
reg [3:0] ch_en = 0; // channel enable
wire [31:0] cmd_data;
wire cmd_a; // just 1 bit
wire cmd_we;
wire set_mode_w;
wire set_status_w;
wire [ GPIO_N-1:0] ds_en_m;
wire [ GPIO_N-1:0] da_en_m;
wire [ GPIO_N-1:0] db_en_m;
wire [ GPIO_N-1:0] dc_en_m;
wire [ GPIO_N-1:0] io_t; // tri-state for the I/Os
wire [ GPIO_N-1:0] io_do; // data out for the I/Os
assign set_mode_w = cmd_we && (cmd_a == GPIO_SET_PINS);
assign set_status_w = cmd_we && (cmd_a == GPIO_SET_STATUS);
assign dc_en_m = dc_en & {GPIO_N{ch_en[3]}};
assign db_en_m = db_en & {GPIO_N{ch_en[2]}} & ~dc_en_m;
assign da_en_m = da_en & {GPIO_N{ch_en[1]}} & ~dc_en_m & ~db_en_m;
assign ds_en_m = ds_en & {GPIO_N{ch_en[0]}} & ~dc_en_m & ~db_en_m & ~da_en_m;
assign io_do = (dc_en_m & dc) |
(db_en_m & db) |
(da_en_m & da) |
(ds_en_m & ds);
assign io_t = ~(dc_en_m | db_en_m | da_en_m | ds_en_m);
// 0 0 0 - no change -
// 0 1 1 1 0
// 1 0 2 1 1
// 1 1 3 0 0
always @ (posedge rst or posedge mclk) begin
if (rst) ch_en[0] <= 0;
else if (set_mode_w && cmd_data[GPIO_PORTEN + 1]) ch_en[0] <= cmd_data[GPIO_PORTEN + 0];
if (rst) ch_en[1] <= 0;
else if (set_mode_w && cmd_data[GPIO_PORTEN + 3]) ch_en[1] <= cmd_data[GPIO_PORTEN + 2];
if (rst) ch_en[2] <= 0;
else if (set_mode_w && cmd_data[GPIO_PORTEN + 5]) ch_en[2] <= cmd_data[GPIO_PORTEN + 4];
if (rst) ch_en[3] <= 0;
else if (set_mode_w && cmd_data[GPIO_PORTEN + 7]) ch_en[3] <= cmd_data[GPIO_PORTEN + 6];
end
generate
genvar i;
for (i=0; i < GPIO_N; i=i+1) begin: gpio_block
gpio_bit gpio_bit_i (
.rst (rst), // input
.clk (mclk), // input
.we (set_mode_w), // input
.d_in (cmd_data[2*i +: 2]), // input[1:0]
.d_out (ds[i]), // output
.en_out (ds_en[i]) // output
);
end
iobuf #(
.DRIVE (GPIO_DRIVE),
.IBUF_LOW_PWR (GPIO_IBUF_LOW_PWR),
.IOSTANDARD (GPIO_IOSTANDARD),
.SLEW (GPIO_SLEW)
) iobuf_gpio_i (
.O (io_pins[i]), // output
.IO (ext_pins[i]), // inout
.I (io_do[i]), // input
.T (io_t[i]) // input
);
endgenerate
cmd_deser #(
.ADDR (GPIO_ADDR),
.ADDR_MASK (GPIO_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (1),
.DATA_WIDTH (32)
) cmd_deser_32bit_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (cmd_a), // output[0:0]
.data (cmd_data), // output[31:0]
.we (cmd_we) // output
);
status_generate #(
.STATUS_REG_ADDR (GPIO_STATUS_REG_ADDR),
.PAYLOAD_BITS (12),
.REGISTER_STATUS (1)
) status_generate_i (
.rst (), // input
.clk (mclk), // input
.we (set_status_w), // input
.wd (cmd_data[7:0]), // input[7:0]
.status ({io_pins,2'b0}), // input[11:0]
.ad (status_ad), // output[7:0]
.rq (status_rq), // output
.start (status_start) // input
);
endmodule
module gpio_bit (
input rst, // global reset
input clk, // system clock
input we,
input [1:0] d_in, // input bits
output d_out, // output data
output en_out); // enable output
reg d_r = 0;
reg en_r = 0;
assign d_out = d_r;
assign en_out = en_r;
always @ (posedge rst or posedge clk) begin
if (rst) d_r <= 0;
else if (we && (|d_in)) d_r <= !d_in[0];
if (rst) en_r <= 0;
else if (we && (|d_in)) en_r <= !(&d_in);
end
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment