Skip to content

Commit

Permalink
rtl/keynsham: initial support for GPIO.
Browse files Browse the repository at this point in the history
The Keynsham SoC on the DE0-CV has GPIO pins connected to the 7-segment
displays, push buttons and switches.  The DE0-nano does not currently
have any GPIO pins connected.
  • Loading branch information
jamieiles committed Apr 1, 2015
1 parent ad9f462 commit f3a9d8a
Show file tree
Hide file tree
Showing 13 changed files with 261 additions and 9 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ Keynsham is a SoC using Oldland as the core and has a number of peripherals:
- Interrupt controller.
- UART.
- SPI master.
- GPIO.

There is a C model along with Icarus and Verilator RTL simulations. The
Keynsham SoC can be synthesized to run on a Terasic DE0 Nano. There are ports
of binutils, gcc and u-boot available.
Keynsham SoC can be synthesized to run on a Terasic DE0 Nano or DE0-CV. There
are ports of binutils, gcc and u-boot available.

For documentation see the [Oldland CPU site](http://jamieiles.github.io/oldland-cpu/)
20 changes: 20 additions & 0 deletions config/de0-cv.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,26 @@
address: "0x80004000",
size: "0x00004000",
regmap: spimaster
},
# Two banks of GPIO:
# - bank 1 at offset 16
# - [31:28]: push buttons
# - [27:26]: no connection
# - [25:16]: switches
# - [15:15]: no connection
# - [14:8]: 7-seg 5
# - [7:7]: no connection
# - [7:0]: 7-seg 4
# - bank 0 at offset 0
# - [30:24]: 7-seg 3
# - [22:16]: 7-seg 2
# - [14:8]: 7-seg 1
# - [6:0]: 7-seg 0
{
name: gpio,
address: "0x80008000",
size: "0x00001000",
regmap: gpio
}
]
}
14 changes: 14 additions & 0 deletions config/regmaps/gpio.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
gpio_value: {
offset: 0
},
gpio_output_enable: {
offset: 4
},
gpio_set: {
offset: 8
},
gpio_clear: {
offset: 12
},
}
1 change: 1 addition & 0 deletions fpga/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
*/spimaster_defines.v
*/timer_defines.v
*/uart_defines.v
*/gpio_defines.v
72 changes: 72 additions & 0 deletions fpga/de0-cv/keynsham-soc.qsf
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,73 @@ set_location_assignment PIN_R22 -to spi_clk2
set_location_assignment PIN_T22 -to spi_mosi2
set_location_assignment PIN_P22 -to rst_in_n

# Hex 0
set_location_assignment PIN_U21 -to gpio[0]
set_location_assignment PIN_V21 -to gpio[1]
set_location_assignment PIN_W22 -to gpio[2]
set_location_assignment PIN_W21 -to gpio[3]
set_location_assignment PIN_Y22 -to gpio[4]
set_location_assignment PIN_Y21 -to gpio[5]
set_location_assignment PIN_AA22 -to gpio[6]
# Hex 1
set_location_assignment PIN_AA20 -to gpio[8]
set_location_assignment PIN_AB20 -to gpio[9]
set_location_assignment PIN_AA19 -to gpio[10]
set_location_assignment PIN_AA18 -to gpio[11]
set_location_assignment PIN_AB18 -to gpio[12]
set_location_assignment PIN_AA17 -to gpio[13]
set_location_assignment PIN_U22 -to gpio[14]
# Hex 2
set_location_assignment PIN_Y19 -to gpio[16]
set_location_assignment PIN_AB17 -to gpio[17]
set_location_assignment PIN_AA10 -to gpio[18]
set_location_assignment PIN_Y14 -to gpio[19]
set_location_assignment PIN_V14 -to gpio[20]
set_location_assignment PIN_AB22 -to gpio[21]
set_location_assignment PIN_AB21 -to gpio[22]
# Hex 3
set_location_assignment PIN_Y16 -to gpio[24]
set_location_assignment PIN_W16 -to gpio[25]
set_location_assignment PIN_Y17 -to gpio[26]
set_location_assignment PIN_V16 -to gpio[27]
set_location_assignment PIN_U17 -to gpio[28]
set_location_assignment PIN_V18 -to gpio[29]
set_location_assignment PIN_V19 -to gpio[30]
# Hex 4
set_location_assignment PIN_U20 -to gpio[32]
set_location_assignment PIN_Y20 -to gpio[33]
set_location_assignment PIN_V20 -to gpio[34]
set_location_assignment PIN_U16 -to gpio[35]
set_location_assignment PIN_U15 -to gpio[36]
set_location_assignment PIN_Y15 -to gpio[37]
set_location_assignment PIN_P9 -to gpio[38]
# Hex 5
set_location_assignment PIN_N9 -to gpio[40]
set_location_assignment PIN_M8 -to gpio[41]
set_location_assignment PIN_T14 -to gpio[42]
set_location_assignment PIN_P14 -to gpio[43]
set_location_assignment PIN_C1 -to gpio[44]
set_location_assignment PIN_C2 -to gpio[45]
set_location_assignment PIN_W19 -to gpio[46]

# Push buttons
set_location_assignment PIN_U7 -to gpio[60]
set_location_assignment PIN_W9 -to gpio[61]
set_location_assignment PIN_M7 -to gpio[62]
set_location_assignment PIN_M6 -to gpio[63]

# Switches
set_location_assignment PIN_U13 -to gpio[48]
set_location_assignment PIN_V13 -to gpio[49]
set_location_assignment PIN_T13 -to gpio[50]
set_location_assignment PIN_T12 -to gpio[51]
set_location_assignment PIN_AA15 -to gpio[52]
set_location_assignment PIN_AB15 -to gpio[53]
set_location_assignment PIN_AA14 -to gpio[54]
set_location_assignment PIN_AA13 -to gpio[55]
set_location_assignment PIN_AB13 -to gpio[56]
set_location_assignment PIN_AB12 -to gpio[57]

# Classic Timing Assignments
# ==========================
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
Expand Down Expand Up @@ -191,7 +258,9 @@ set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to s_banksel
# ==================
set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to uart_tx
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to uart_rx
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to gpio[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to s_*
set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to gpio[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to sdr_clk
set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to running
set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to spi_cs0_active
Expand Down Expand Up @@ -231,6 +300,7 @@ set_global_assignment -name VERILOG_FILE ../../rtl/sdram/rtl/counter.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_sdram.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_uart.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_spimaster.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_gpio.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_ram.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_irq.v
set_global_assignment -name VERILOG_FILE ../../rtl/keynsham/keynsham_timer.v
Expand Down Expand Up @@ -276,4 +346,6 @@ set_instance_assignment -name MATCH_PLL_COMPENSATION_CLOCK ON -to "sys_pll:pll|o


set_global_assignment -name QIP_FILE ram.qip


set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
4 changes: 4 additions & 0 deletions fpga/de0-cv/keynsham-soc.sdc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ set_multicycle_path -setup -end -from sdram_clk -to $sys_clk 2
set_false_path -from [get_ports uart_rx]
set_false_path -to [get_ports uart_tx]

# GPI
set_false_path -from [get_ports gpio[*]]
set_false_path -to [get_ports gpio[*]]

# Status LEDs
set_false_path -to [get_ports running]
set_false_path -to [get_ports spi_cs0_active]
Expand Down
6 changes: 4 additions & 2 deletions rtl/fpga/de0cv/toplevel.v
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ module toplevel(input wire clk,
output wire spi_mosi2,
input wire spi_miso2,
/* Ethernet control */
output reg ethernet_reset_n);
output reg ethernet_reset_n,
inout wire [63:0] gpio);

wire sys_clk;
wire dbg_clk;
Expand Down Expand Up @@ -102,7 +103,8 @@ keynsham_soc #(.spi_num_cs(2))
.miso(spi_miso),
.mosi(spi_mosi),
.sclk(spi_clk),
.spi_ncs(spi_ncs));
.spi_ncs(spi_ncs),
.gpio(gpio));

/*
* Make the effects of running a little more visible - if we run for at least
Expand Down
92 changes: 92 additions & 0 deletions rtl/keynsham/keynsham_gpio.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
`ifdef GPIO_ADDRESS
module keynsham_gpio(input wire clk,
/* Data bus. */
input wire bus_access,
output wire bus_cs,
input wire [29:0] bus_addr,
input wire [31:0] bus_wr_val,
input wire bus_wr_en,
input wire [3:0] bus_bytesel,
output reg bus_error,
output reg bus_ack,
output wire [31:0] bus_data,
/* GPIO */
inout wire [ngpio - 1:0] gpio);

parameter num_banks = 2;
parameter bus_address = 32'h0;
parameter bus_size = 32'h0;
localparam ngpio = num_banks * 32;

wire banksel = bus_addr[2];
wire [1:0] regsel = bus_addr[1:0];
wire access_value = {28'b0, regsel, 2'b00} == `GPIO_VALUE_REG_OFFS;
wire access_oe = {28'b0, regsel, 2'b00} == `GPIO_OUTPUT_ENABLE_REG_OFFS;
wire access_set = {28'b0, regsel, 2'b00} == `GPIO_SET_REG_OFFS;
wire access_clr = {28'b0, regsel, 2'b00} == `GPIO_CLEAR_REG_OFFS;

reg [31:0] data = 32'b0;
assign bus_data = bus_ack ? data : 32'b0;

cs_gen #(.address(bus_address), .size(bus_size))
d_cs_gen(.bus_addr(bus_addr), .cs(bus_cs));

reg [ngpio - 1:0] gpio_internal = {ngpio{1'bz}};
assign gpio = gpio_internal;

reg [31:0] outputs[num_banks - 1:0];
reg [31:0] oe[num_banks - 1:0];
reg [$clog2(ngpio):0] pin = {$clog2(ngpio) + 1{1'b0}};
reg [31:0] input_banks[num_banks - 1:0];

initial begin
bus_error = 1'b0;
bus_ack = 1'b0;

/* verilator lint_off WIDTH */
for (pin = 0; pin < ngpio; pin = pin + 1'b1) begin
gpio_internal[pin] = 1'bz;
outputs[pin / 32][pin % 32] = 1'b0;
oe[pin / 32][pin % 32] = 1'b0;
input_banks[pin / 32][pin % 32] = 1'b0;
end
/* verilator lint_on WIDTH */
end

always @(*) begin
/* verilator lint_off WIDTH */
for (pin = 0; pin < ngpio; pin = pin + 1'b1) begin
gpio_internal[pin] = oe[pin / 32][pin % 32] ? outputs[pin / 32][pin % 32] : 1'bz;
input_banks[pin / 32][pin % 32] = gpio[pin];
end
/* verilator lint_on WIDTH */
end

always @(*) begin
if (access_value)
data = (outputs[banksel] & oe[banksel]) | (input_banks[banksel] & ~oe[banksel]);
else if (access_oe)
data = oe[banksel];
else
data = 32'b0;
end

always @(posedge clk) begin
if (bus_access && bus_cs && bus_wr_en && bus_bytesel == 4'hf) begin
if (access_oe)
oe[banksel] <= bus_wr_val;
else if (access_set)
outputs[banksel] <= outputs[banksel] | bus_wr_val;
else if (access_clr)
outputs[banksel] <= outputs[banksel] & ~bus_wr_val;
end
end

always @(posedge clk)
bus_ack <= bus_access & bus_cs;

always @(posedge clk)
bus_error <= bus_access & bus_cs & (bus_bytesel != 4'hf);

endmodule
`endif /* GPIO_ADDRESS */
41 changes: 37 additions & 4 deletions rtl/keynsham/keynsham_soc.v
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ module keynsham_soc(input wire clk,
input wire dbg_wr_en,
input wire dbg_req,
output wire dbg_ack,
`ifdef GPIO_ADDRESS
inout wire [63:0] gpio,
`endif
/* SPI bus. */
input wire miso,
output wire mosi,
Expand Down Expand Up @@ -87,6 +90,10 @@ wire [31:0] i_sdram_data;
wire i_sdram_ack;
wire i_sdram_error;

wire [31:0] gpio_data;
wire gpio_ack;
wire gpio_error;

wire [31:0] cpu_d_out;

/*
Expand All @@ -109,23 +116,26 @@ wire uart_cs;
wire irq_cs;
wire timer_cs;
wire spimaster_cs;
wire gpio_cs;

wire d_default_cs = ~(ram_cs | rom_cs | d_sdram_cs |
d_sdram_ctrl_cs | uart_cs | irq_cs |
timer_cs | spimaster_cs);
timer_cs | spimaster_cs | gpio_cs);
wire i_default_cs = ~(ram_i_cs | rom_i_cs | i_sdram_cs);

wire d_ack = uart_ack | ram_ack | d_sdram_ack | rom_ack | irq_ack |
timer_ack | d_default_ack | spimaster_ack;
timer_ack | d_default_ack | spimaster_ack | gpio_ack;
wire d_error = uart_error | d_sdram_error | irq_error |
timer_error | d_default_error | spimaster_error;
timer_error | d_default_error | spimaster_error |
gpio_error;

wire i_access;
wire i_ack = i_ram_ack | i_rom_ack | i_default_ack | i_sdram_ack;
wire i_error = i_default_error | i_sdram_error;

assign d_data = ram_data | uart_data | d_sdram_data | rom_data |
irq_data | timer_data | d_wr_val | spimaster_data;
irq_data | timer_data | d_wr_val | spimaster_data |
gpio_data;
assign i_data = i_ram_data | i_rom_data | i_sdram_data;

keynsham_ram #(.bus_address(`RAM_ADDRESS),
Expand Down Expand Up @@ -257,6 +267,29 @@ keynsham_spimaster #(.bus_address(`SPIMASTER_ADDRESS),
.sclk(sclk),
.ncs(spi_ncs));

`ifdef GPIO_ADDRESS
keynsham_gpio #(.bus_address(`GPIO_ADDRESS),
.bus_size(`GPIO_SIZE),
.num_banks(2))
gpioinst(.clk(clk),
.bus_access(d_access),
.bus_cs(gpio_cs),
.bus_addr(d_addr),
.bus_wr_val(d_data),
.bus_wr_en(d_wr_en),
.bus_bytesel(d_bytesel),
.bus_error(gpio_error),
.bus_ack(gpio_ack),
.bus_data(gpio_data),
.gpio(gpio));

`else
assign gpio_data = 32'b0;
assign gpio_ack = 1'b0;
assign gpio_error = 1'b0;
assign gpio_cs = 1'b0;
`endif

oldland_cpu #(.icache_size(`ICACHE_SIZE),
.icache_line_size(`ICACHE_LINE_SIZE),
.icache_num_ways(`ICACHE_NUM_WAYS),
Expand Down
2 changes: 1 addition & 1 deletion verif/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ add_custom_target(generate

add_custom_target(lint ALL
DEPENDS generate
COMMAND verilator -Wfuture-PINCONNECTEMPTY --lint-only ${VERILATOR_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR} ${VERILATOR_INCLUDES} -D__ICARUS__ oldland_defines.v ${CMAKE_CURRENT_BINARY_DIR}/../config/keynsham_defines.v ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/keynsham/keynsham_soc.v)
COMMAND verilator -Wfuture-PINCONNECTEMPTY -Wfuture-PINNOCONNECT --lint-only ${VERILATOR_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR} ${VERILATOR_INCLUDES} -D__ICARUS__ oldland_defines.v ${CMAKE_CURRENT_BINARY_DIR}/../config/keynsham_defines.v ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/keynsham/keynsham_soc.v)

INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/decode.hex DESTINATION lib)
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/oldland-rtlsim DESTINATION bin)
Expand Down
1 change: 1 addition & 0 deletions verif/icarus/oldland.cf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cpu_tb.v
../../rtl/keynsham/keynsham_soc.v
../../rtl/keynsham/keynsham_uart.v
../../rtl/keynsham/keynsham_spimaster.v
../../rtl/keynsham/keynsham_gpio.v
../../rtl/keynsham/keynsham_irq.v
../../rtl/keynsham/keynsham_timer.v
../../rtl/keynsham/keynsham_timer_block.v
Expand Down
1 change: 1 addition & 0 deletions verif/verilator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ option(TRACE_VERILATOR "Enable tracing in verilator model" OFF)
set(VERILATOR_FLAGS
--cc -DSIMULATION=1 -DUSE_DEBUG_UART=1
-Wfuture-PINCONNECTEMPTY
-Wfuture-PINNOCONNECT
-DOLDLAND_ROM_PATH=\\\"${CMAKE_INSTALL_PREFIX}/lib/\\\")

if(TRACE_VERILATOR)
Expand Down
Loading

0 comments on commit f3a9d8a

Please sign in to comment.