mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-08-01 03:06:05 -04:00
Make initial public release
This commit is contained in:
commit
715de60f4a
251 changed files with 881225 additions and 0 deletions
342
hw/application_fpga/tb/application_fpga_verilator.cc
Normal file
342
hw/application_fpga/tb/application_fpga_verilator.cc
Normal file
|
@ -0,0 +1,342 @@
|
|||
//======================================================================
|
||||
//
|
||||
// application_fpga_verilator.cc
|
||||
// -----------------------------
|
||||
// Wrapper to allow simulation of the application_fpga using Verilator.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2022 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
#include <pty.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Vapplication_fpga.h"
|
||||
#include "verilated.h"
|
||||
|
||||
// Joachim says:
|
||||
// Clock: 12 MHz, 38400 bps
|
||||
// Divisor = 12*10E6 / 38400 = 312
|
||||
#define BIT_DIV 312
|
||||
|
||||
struct uart {
|
||||
int bit_div;
|
||||
unsigned int ts;
|
||||
|
||||
unsigned int tx_next_ts;
|
||||
unsigned int rx_next_ts;
|
||||
|
||||
int rx_state; /* 0, (idle), 1 (start), 2..9 (data), 10 (stop), 11 (stop end) */
|
||||
int tx_state; /* 0, (idle), 1..8 (data), 9 (stop), 10 (stop end) */
|
||||
uint8_t tx_data;
|
||||
uint8_t rx_data;
|
||||
int rx_has_data;
|
||||
int tx_has_data;
|
||||
uint8_t *tx;
|
||||
uint8_t *rx;
|
||||
};
|
||||
|
||||
void uart_init(struct uart *u, uint8_t *tx, uint8_t *rx, int bit_div);
|
||||
void uart_tick(struct uart *u);
|
||||
int uart_can_send(struct uart *u);
|
||||
int uart_send(struct uart *u, uint8_t data);
|
||||
int uart_recv(struct uart *u, uint8_t *data);
|
||||
|
||||
void uart_init(struct uart *u, uint8_t *tx, uint8_t *rx, int bit_div)
|
||||
{
|
||||
u->bit_div = bit_div;
|
||||
u->ts = 0;
|
||||
u->tx_next_ts = 0;
|
||||
u->rx_next_ts = 0;
|
||||
u->rx_state = 0;
|
||||
u->tx_state = 0;
|
||||
u->tx_data = 0;
|
||||
u->rx_data = 0;
|
||||
u->rx_has_data = 0;
|
||||
u->tx_has_data = 0;
|
||||
u->tx = tx;
|
||||
*u->tx = 1;
|
||||
u->rx = rx;
|
||||
}
|
||||
|
||||
void uart_rx_tick(struct uart *u)
|
||||
{
|
||||
if (u->rx_state == 0) {
|
||||
// Idle
|
||||
if (!u->rx_has_data && !*u->rx) { // Active low
|
||||
u->rx_next_ts = u->ts + u->bit_div / 2; // sample mid-point
|
||||
u->rx_state = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->rx_state == 1) {
|
||||
// Start
|
||||
if (u->ts < u->rx_next_ts)
|
||||
return;
|
||||
|
||||
if (*u->rx) {
|
||||
u->rx_state = 0; // Back to idle, shouldn't happen
|
||||
return;
|
||||
}
|
||||
|
||||
u->rx_next_ts += u->bit_div;
|
||||
u->rx_data = 0;
|
||||
u->rx_state = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->rx_state > 1 && u->rx_state < 10) {
|
||||
// Data
|
||||
if (u->ts < u->rx_next_ts)
|
||||
return;
|
||||
|
||||
u->rx_next_ts += u->bit_div;
|
||||
u->rx_data |= (!!*u->rx) << (u->rx_state - 2);
|
||||
u->rx_state++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->rx_state == 10) {
|
||||
// Stop
|
||||
if (u->ts < u->rx_next_ts)
|
||||
return;
|
||||
|
||||
if (!*u->rx) {
|
||||
u->rx_state = 0; // Back to dle, shouldn't happen
|
||||
return;
|
||||
}
|
||||
|
||||
u->rx_next_ts += u->bit_div/2;
|
||||
u->rx_has_data = 1;
|
||||
u->rx_state = 11;
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->rx_state == 11) {
|
||||
if (u->ts < u->rx_next_ts)
|
||||
return;
|
||||
|
||||
u->rx_state = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int uart_recv(struct uart *u, uint8_t *data)
|
||||
{
|
||||
if (u->rx_has_data && (u->rx_state == 0 || u->rx_state == 11)) {
|
||||
*data = u->rx_data;
|
||||
u->rx_has_data = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_tx_tick(struct uart *u)
|
||||
{
|
||||
if (u->tx_state == 0) {
|
||||
// Idle
|
||||
if (u->tx_has_data) {
|
||||
u->tx_next_ts = u->ts + u->bit_div;
|
||||
*u->tx = 0; // Start
|
||||
u->tx_state = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->tx_state > 0 && u->tx_state < 9) {
|
||||
// Data
|
||||
if (u->ts < u->tx_next_ts)
|
||||
return;
|
||||
|
||||
u->tx_next_ts += u->bit_div;
|
||||
*u->tx = (u->tx_data >> (u->tx_state - 1)) & 1;
|
||||
u->tx_state++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->tx_state == 9) {
|
||||
// Stop
|
||||
if (u->ts < u->tx_next_ts)
|
||||
return;
|
||||
|
||||
u->tx_next_ts += u->bit_div;
|
||||
*u->tx = 1; // Stop
|
||||
u->tx_has_data = 0;
|
||||
u->tx_state = 10;
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->tx_state == 10) {
|
||||
if (u->ts < u->tx_next_ts)
|
||||
return;
|
||||
|
||||
u->tx_state = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int uart_can_send(struct uart *u)
|
||||
{
|
||||
return !u->tx_has_data;
|
||||
}
|
||||
|
||||
int uart_send(struct uart *u, uint8_t data)
|
||||
{
|
||||
if (!uart_can_send(u))
|
||||
return 0;
|
||||
|
||||
u->tx_has_data = 1;
|
||||
u->tx_data = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void uart_tick(struct uart *u)
|
||||
{
|
||||
u->ts++;
|
||||
|
||||
uart_rx_tick(u);
|
||||
uart_tx_tick(u);
|
||||
}
|
||||
|
||||
struct pty {
|
||||
int amaster;
|
||||
int aslave;
|
||||
char slave[32];
|
||||
};
|
||||
|
||||
int pty_init(struct pty *p);
|
||||
int pty_can_recv(struct pty *p);
|
||||
int pty_recv(struct pty *p, uint8_t *data);
|
||||
void pty_send(struct pty *p, uint8_t data);
|
||||
|
||||
int pty_init(struct pty *p)
|
||||
{
|
||||
struct termios tty;
|
||||
int flags;
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
if (openpty(&p->amaster, &p->aslave, p->slave, NULL, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
if (tcgetattr(p->aslave, &tty) < 0)
|
||||
return -1;
|
||||
cfmakeraw(&tty);
|
||||
if (tcsetattr(p->aslave, TCSAFLUSH, &tty) < 0)
|
||||
return -1;
|
||||
|
||||
if ((flags = fcntl(p->amaster, F_GETFL, 0) < 0))
|
||||
return -1;
|
||||
|
||||
flags |= O_NONBLOCK;
|
||||
if (fcntl(p->amaster, F_SETFL, flags) < 0)
|
||||
return -1;
|
||||
|
||||
printf("pty: %s\n", p->slave);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pty_can_recv(struct pty *p)
|
||||
{
|
||||
struct pollfd fds = {p->amaster, POLLIN, 0};
|
||||
char c;
|
||||
|
||||
return poll(&fds, 1, 0) == 1;
|
||||
}
|
||||
|
||||
int pty_recv(struct pty *p, uint8_t *data)
|
||||
{
|
||||
return read(p->amaster, data, 1) == 1;
|
||||
}
|
||||
|
||||
void pty_send(struct pty *p, uint8_t data)
|
||||
{
|
||||
ssize_t i __attribute__((unused));
|
||||
|
||||
i = write(p->amaster, &data, 1);
|
||||
}
|
||||
|
||||
volatile int touch_cyc = 0;
|
||||
|
||||
void sighandler(int)
|
||||
{
|
||||
touch_cyc = 1000;
|
||||
}
|
||||
|
||||
void touch(uint8_t *touch_event)
|
||||
{
|
||||
if (touch_cyc > 0) {
|
||||
touch_cyc--;
|
||||
*touch_event = 1;
|
||||
} else {
|
||||
*touch_event = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vluint64_t main_time = 0;
|
||||
double sc_time_stamp()
|
||||
{
|
||||
return main_time;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
Verilated::commandArgs(argc, argv);
|
||||
int r = 0, g = 0, b = 0;
|
||||
Vapplication_fpga top;
|
||||
struct uart u;
|
||||
struct pty p;
|
||||
int err;
|
||||
|
||||
if (signal(SIGUSR1, sighandler) == SIG_ERR)
|
||||
return -1;
|
||||
printf("generate touch event: \"$ kill -USR1 %d\"\n", (int)getpid());
|
||||
|
||||
err = pty_init(&p);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
uart_init(&u, &top.interface_tx, &top.interface_rx, BIT_DIV);
|
||||
|
||||
top.clk = 0;
|
||||
|
||||
while (!Verilated::gotFinish()) {
|
||||
uint8_t to_host = 0;
|
||||
|
||||
top.clk = !top.clk;
|
||||
|
||||
if (main_time < 10)
|
||||
goto skip;
|
||||
|
||||
if (!top.clk) {
|
||||
touch(&top.touch_event);
|
||||
uart_tick(&u);
|
||||
}
|
||||
|
||||
if (pty_can_recv(&p) && uart_can_send(&u)) {
|
||||
uint8_t from_host = 0;
|
||||
|
||||
pty_recv(&p, &from_host);
|
||||
uart_send(&u, from_host);
|
||||
}
|
||||
|
||||
if (uart_recv(&u, &to_host) == 1) {
|
||||
pty_send(&p, to_host);
|
||||
}
|
||||
skip:
|
||||
main_time++;
|
||||
top.eval();
|
||||
|
||||
}
|
||||
}
|
482
hw/application_fpga/tb/application_fpga_vsim.v
Normal file
482
hw/application_fpga/tb/application_fpga_vsim.v
Normal file
|
@ -0,0 +1,482 @@
|
|||
//======================================================================
|
||||
//
|
||||
// application_fpga.v
|
||||
// ------------------
|
||||
// Top level module of the application FPGA.
|
||||
// The design exposes a UART interface to allow a host to
|
||||
// send commands and receive resposes as needed load, execute and
|
||||
// communicate with applications.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2022 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
//`define VERBOSE
|
||||
|
||||
`ifdef VERBOSE
|
||||
`define verbose(debug_command) debug_command
|
||||
`else
|
||||
`define verbose(debug_command)
|
||||
`endif
|
||||
|
||||
|
||||
module application_fpga(
|
||||
input wire clk,
|
||||
|
||||
output wire valid,
|
||||
output wire [03 : 0] wstrb,
|
||||
output wire [31 : 0] addr,
|
||||
output wire [31 : 0] wdata,
|
||||
output wire [31 : 0] rdata,
|
||||
output wire ready,
|
||||
|
||||
output wire interface_rx,
|
||||
input wire interface_tx,
|
||||
|
||||
input wire touch_event,
|
||||
|
||||
input wire app_gpio1,
|
||||
input wire app_gpio2,
|
||||
output wire app_gpio3,
|
||||
output wire app_gpio4,
|
||||
|
||||
output wire led_r,
|
||||
output wire led_g,
|
||||
output wire led_b
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Local parameters
|
||||
//----------------------------------------------------------------
|
||||
// Top level mem area prefixes.
|
||||
localparam ROM_PREFIX = 2'h0;
|
||||
localparam RAM_PREFIX = 2'h1;
|
||||
localparam RESERVED_PREFIX = 2'h2;
|
||||
localparam MMIO_PREFIX = 2'h3;
|
||||
|
||||
// MMIO core mem sub-prefixes.
|
||||
localparam TRNG_PREFIX = 6'h00;
|
||||
localparam TIMER_PREFIX = 6'h01;
|
||||
localparam UDS_PREFIX = 6'h02;
|
||||
localparam UART_PREFIX = 6'h03;
|
||||
localparam TOUCH_SENSE_PREFIX = 6'h04;
|
||||
localparam MTA1_PREFIX = 6'h3f;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Registers, memories with associated wires.
|
||||
//----------------------------------------------------------------
|
||||
reg [31 : 0] muxed_rdata_reg;
|
||||
reg [31 : 0] muxed_rdata_new;
|
||||
|
||||
reg muxed_ready_reg;
|
||||
reg muxed_ready_new;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Wires.
|
||||
//----------------------------------------------------------------
|
||||
wire reset_n;
|
||||
|
||||
wire cpu_valid;
|
||||
wire [03 : 0] cpu_wstrb;
|
||||
wire [31 : 0] cpu_addr;
|
||||
wire [31 : 0] cpu_wdata;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg rom_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg [11 : 0] rom_address;
|
||||
wire [31 : 0] rom_read_data;
|
||||
wire rom_ready;
|
||||
|
||||
reg ram_cs;
|
||||
reg [3 : 0] ram_we;
|
||||
reg [14 : 0] ram_address;
|
||||
reg [31 : 0] ram_write_data;
|
||||
wire [31 : 0] ram_read_data;
|
||||
wire ram_ready;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg trng_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg trng_we;
|
||||
reg [7 : 0] trng_address;
|
||||
reg [31 : 0] trng_write_data;
|
||||
wire [31 : 0] trng_read_data;
|
||||
wire trng_ready;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg timer_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg timer_we;
|
||||
reg [7 : 0] timer_address;
|
||||
reg [31 : 0] timer_write_data;
|
||||
wire [31 : 0] timer_read_data;
|
||||
wire timer_ready;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg uds_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg [7 : 0] uds_address;
|
||||
wire [31 : 0] uds_read_data;
|
||||
wire uds_ready;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg uart_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg uart_we;
|
||||
reg [7 : 0] uart_address;
|
||||
reg [31 : 0] uart_write_data;
|
||||
wire [31 : 0] uart_read_data;
|
||||
wire uart_ready;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg touch_sense_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg touch_sense_we;
|
||||
reg [7 : 0] touch_sense_address;
|
||||
wire [31 : 0] touch_sense_read_data;
|
||||
wire touch_sense_ready;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
reg mta1_cs;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
reg mta1_we;
|
||||
reg [7 : 0] mta1_address;
|
||||
reg [31 : 0] mta1_write_data;
|
||||
wire [31 : 0] mta1_read_data;
|
||||
wire mta1_ready;
|
||||
wire fw_app_mode;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Concurrent assignments.
|
||||
//----------------------------------------------------------------
|
||||
assign valid = cpu_valid;
|
||||
assign wstrb = cpu_wstrb;
|
||||
assign addr = cpu_addr;
|
||||
assign wdata = cpu_wdata;
|
||||
assign rdata = muxed_rdata_reg;
|
||||
assign ready = muxed_ready_reg;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Module instantiations.
|
||||
//----------------------------------------------------------------
|
||||
reset_gen #(.RESET_CYCLES(200))
|
||||
reset_gen_inst(.clk(clk), .rst_n(reset_n));
|
||||
|
||||
|
||||
picorv32 #(
|
||||
.ENABLE_COUNTERS(0),
|
||||
.LATCHED_MEM_RDATA(0),
|
||||
.TWO_STAGE_SHIFT(0),
|
||||
.TWO_CYCLE_ALU(0),
|
||||
.CATCH_MISALIGN(0),
|
||||
.CATCH_ILLINSN(0),
|
||||
.COMPRESSED_ISA(1),
|
||||
.ENABLE_MUL(1),
|
||||
.ENABLE_DIV(0),
|
||||
.BARREL_SHIFTER(0)
|
||||
) cpu(
|
||||
.clk(clk),
|
||||
.resetn(reset_n),
|
||||
|
||||
.mem_valid(cpu_valid),
|
||||
.mem_addr (cpu_addr),
|
||||
.mem_wdata(cpu_wdata),
|
||||
.mem_wstrb(cpu_wstrb),
|
||||
.mem_rdata(muxed_rdata_reg),
|
||||
.mem_ready(muxed_ready_reg),
|
||||
|
||||
// Defined unsed ports. Makes lint happy,
|
||||
// but still needs to help lint with empty ports.
|
||||
/* verilator lint_off PINCONNECTEMPTY */
|
||||
.irq(32'h0),
|
||||
.eoi(),
|
||||
.trap(),
|
||||
.trace_valid(),
|
||||
.trace_data(),
|
||||
.mem_instr(),
|
||||
.mem_la_read(),
|
||||
.mem_la_write(),
|
||||
.mem_la_addr(),
|
||||
.mem_la_wdata(),
|
||||
.mem_la_wstrb(),
|
||||
.pcpi_valid(),
|
||||
.pcpi_insn(),
|
||||
.pcpi_rs1(),
|
||||
.pcpi_rs2(),
|
||||
.pcpi_wr(1'h0),
|
||||
.pcpi_rd(32'h0),
|
||||
.pcpi_wait(1'h0),
|
||||
.pcpi_ready(1'h0)
|
||||
/* verilator lint_on PINCONNECTEMPTY */
|
||||
);
|
||||
|
||||
|
||||
rom rom_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.cs(rom_cs),
|
||||
.address(rom_address),
|
||||
.read_data(rom_read_data),
|
||||
.ready(rom_ready)
|
||||
);
|
||||
|
||||
|
||||
ram ram_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.cs(ram_cs),
|
||||
.we(ram_we),
|
||||
.address(ram_address),
|
||||
.write_data(ram_write_data),
|
||||
.read_data(ram_read_data),
|
||||
.ready(ram_ready)
|
||||
);
|
||||
|
||||
|
||||
timer timer_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.cs(timer_cs),
|
||||
.we(timer_we),
|
||||
.address(timer_address),
|
||||
.write_data(timer_write_data),
|
||||
.read_data(timer_read_data),
|
||||
.ready(timer_ready)
|
||||
);
|
||||
|
||||
|
||||
uds uds_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.cs(uds_cs),
|
||||
.address(uds_address),
|
||||
.read_data(uds_read_data),
|
||||
.ready(uds_ready)
|
||||
);
|
||||
|
||||
|
||||
uart uart_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.rxd(interface_tx),
|
||||
.txd(interface_rx),
|
||||
|
||||
.cs(uart_cs),
|
||||
.we(uart_we),
|
||||
.address(uart_address),
|
||||
.write_data(uart_write_data),
|
||||
.read_data(uart_read_data),
|
||||
.ready(uart_ready)
|
||||
);
|
||||
|
||||
|
||||
touch_sense touch_sense_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.touch_event(touch_event),
|
||||
|
||||
.cs(touch_sense_cs),
|
||||
.we(touch_sense_we),
|
||||
.address(touch_sense_address),
|
||||
.read_data(touch_sense_read_data),
|
||||
.ready(touch_sense_ready)
|
||||
);
|
||||
|
||||
|
||||
mta1 mta1_inst(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.fw_app_mode(fw_app_mode),
|
||||
|
||||
.led_r(led_r),
|
||||
.led_g(led_g),
|
||||
.led_b(led_b),
|
||||
|
||||
.gpio1(app_gpio1),
|
||||
.gpio2(app_gpio2),
|
||||
.gpio3(app_gpio3),
|
||||
.gpio4(app_gpio4),
|
||||
|
||||
.cs(mta1_cs),
|
||||
.we(mta1_we),
|
||||
.address(mta1_address),
|
||||
.write_data(mta1_write_data),
|
||||
.read_data(mta1_read_data),
|
||||
.ready(mta1_ready)
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Reg_update.
|
||||
// Posedge triggered with synchronous, active low reset.
|
||||
//----------------------------------------------------------------
|
||||
always @(posedge clk)
|
||||
begin : reg_update
|
||||
if (!reset_n) begin
|
||||
muxed_ready_reg <= 1'h0;
|
||||
muxed_rdata_reg <= 32'h0;
|
||||
end
|
||||
|
||||
else begin
|
||||
muxed_ready_reg <= muxed_ready_new;
|
||||
muxed_rdata_reg <= muxed_rdata_new;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// cpu_mem_ctrl
|
||||
// CPU memory decode and control logic.
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : cpu_mem_ctrl
|
||||
reg [1 : 0] area_prefix;
|
||||
reg [5 : 0] core_prefix;
|
||||
|
||||
area_prefix = cpu_addr[31 : 30];
|
||||
core_prefix = cpu_addr[29 : 24];
|
||||
|
||||
muxed_ready_new = 1'h0;
|
||||
muxed_rdata_new = 32'h0;
|
||||
|
||||
rom_cs = 1'h0;
|
||||
rom_address = cpu_addr[13 : 2];
|
||||
|
||||
ram_cs = 1'h0;
|
||||
ram_we = cpu_wstrb;
|
||||
ram_address = cpu_addr[16 : 2];
|
||||
ram_write_data = cpu_wdata;
|
||||
|
||||
trng_cs = 1'h0;
|
||||
trng_we = |cpu_wstrb;
|
||||
trng_address = cpu_addr[10 : 2];
|
||||
trng_write_data = cpu_wdata;
|
||||
|
||||
timer_cs = 1'h0;
|
||||
timer_we = |cpu_wstrb;
|
||||
timer_address = cpu_addr[10 : 2];
|
||||
timer_write_data = cpu_wdata;
|
||||
|
||||
uds_cs = 1'h0;
|
||||
uds_address = cpu_addr[10 : 2];
|
||||
|
||||
uart_cs = 1'h0;
|
||||
uart_we = |cpu_wstrb;
|
||||
uart_address = cpu_addr[10 : 2];
|
||||
uart_write_data = cpu_wdata;
|
||||
|
||||
touch_sense_cs = 1'h0;
|
||||
touch_sense_we = |cpu_wstrb;
|
||||
touch_sense_address = cpu_addr[10 : 2];
|
||||
|
||||
mta1_cs = 1'h0;
|
||||
mta1_we = |cpu_wstrb;
|
||||
mta1_address = cpu_addr[10 : 2];
|
||||
mta1_write_data = cpu_wdata;
|
||||
|
||||
if (cpu_valid && !muxed_ready_reg) begin
|
||||
case (area_prefix)
|
||||
ROM_PREFIX: begin
|
||||
`verbose($display("Access to ROM area");)
|
||||
rom_cs = 1'h1;
|
||||
muxed_rdata_new = rom_read_data;
|
||||
muxed_ready_new = rom_ready;
|
||||
end
|
||||
|
||||
RAM_PREFIX: begin
|
||||
`verbose($display("Access to RAM area");)
|
||||
ram_cs = 1'h1;
|
||||
muxed_rdata_new = ram_read_data;
|
||||
muxed_ready_new = ram_ready;
|
||||
end
|
||||
|
||||
RESERVED_PREFIX: begin
|
||||
`verbose($display("Access to RESERVED area");)
|
||||
muxed_rdata_new = 32'h00000000;
|
||||
muxed_ready_new = 1'h1;
|
||||
end
|
||||
|
||||
MMIO_PREFIX: begin
|
||||
`verbose($display("Access to MMIO area");)
|
||||
case (core_prefix)
|
||||
TRNG_PREFIX: begin
|
||||
`verbose($display("Access to TRNG core");)
|
||||
trng_cs = 1'h1;
|
||||
muxed_rdata_new = trng_read_data;
|
||||
muxed_ready_new = trng_ready;
|
||||
end
|
||||
|
||||
TIMER_PREFIX: begin
|
||||
`verbose($display("Access to TIMER core");)
|
||||
timer_cs = 1'h1;
|
||||
muxed_rdata_new = timer_read_data;
|
||||
muxed_ready_new = timer_ready;
|
||||
end
|
||||
|
||||
UDS_PREFIX: begin
|
||||
`verbose($display("Access to UDS core");)
|
||||
uds_cs = 1'h1;
|
||||
muxed_rdata_new = uds_read_data;
|
||||
muxed_ready_new = uds_ready;
|
||||
end
|
||||
|
||||
UART_PREFIX: begin
|
||||
`verbose($display("Access to UART core");)
|
||||
uart_cs = 1'h1;
|
||||
muxed_rdata_new = uart_read_data;
|
||||
muxed_ready_new = uart_ready;
|
||||
end
|
||||
|
||||
TOUCH_SENSE_PREFIX: begin
|
||||
`verbose($display("Access to TOUCH_SENSE core");)
|
||||
touch_sense_cs = 1'h1;
|
||||
muxed_rdata_new = touch_sense_read_data;
|
||||
muxed_ready_new = touch_sense_ready;
|
||||
end
|
||||
|
||||
MTA1_PREFIX: begin
|
||||
`verbose($display("Access to MTA1 core");)
|
||||
mta1_cs = 1'h1;
|
||||
muxed_rdata_new = mta1_read_data;
|
||||
muxed_ready_new = mta1_ready;
|
||||
end
|
||||
|
||||
default: begin
|
||||
`verbose($display("UNDEFINED MMIO");)
|
||||
muxed_rdata_new = 32'h00000000;
|
||||
muxed_ready_new = 1'h1;
|
||||
end
|
||||
endcase // case (core_prefix)
|
||||
end // case: MMIO_PREFIX
|
||||
|
||||
default: begin
|
||||
`verbose($display("UNDEFINED AREA");)
|
||||
muxed_rdata_new = 32'h0;
|
||||
muxed_ready_new = 1'h1;
|
||||
end
|
||||
endcase // case (area_prefix)
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // application_fpga
|
||||
|
||||
//======================================================================
|
||||
// EOF application_fpga.v
|
||||
//======================================================================
|
Loading…
Add table
Add a link
Reference in a new issue