blob: 07667dacdac0aec7128a4a7dd9383a71e84274df [file] [log] [blame]
/****************************************************************************
* fwpayload.v
****************************************************************************/
`define WB_WIRES_ARR(PREFIX,ADDR_WIDTH,DATA_WIDTH,SIZE) \
wire[(SIZE*ADDR_WIDTH)-1:0] PREFIX``adr; \
wire[(SIZE*DATA_WIDTH)-1:0] PREFIX``dat_w; \
wire[(SIZE*DATA_WIDTH)-1:0] PREFIX``dat_r; \
wire[SIZE-1:0] PREFIX``cyc; \
wire[SIZE-1:0] PREFIX``err; \
wire[SIZE*(DATA_WIDTH/8)-1:0] PREFIX``sel; \
wire[SIZE-1:0] PREFIX``stb; \
wire[SIZE-1:0] PREFIX``ack; \
wire[SIZE-1:0] PREFIX``we
`define WB_CONNECT(P_PREFIX,W_PREFIX) \
.P_PREFIX``adr(W_PREFIX``adr), \
.P_PREFIX``dat_w(W_PREFIX``dat_w), \
.P_PREFIX``dat_r(W_PREFIX``dat_r), \
.P_PREFIX``cyc(W_PREFIX``cyc), \
.P_PREFIX``err(W_PREFIX``err), \
.P_PREFIX``sel(W_PREFIX``sel), \
.P_PREFIX``stb(W_PREFIX``stb), \
.P_PREFIX``ack(W_PREFIX``ack), \
.P_PREFIX``we(W_PREFIX``we)
`define WB_CONNECT_ARR(P_PREFIX,W_PREFIX,INDEX,ADDR_WIDTH,DATA_WIDTH) \
.P_PREFIX``adr(W_PREFIX``adr[(INDEX)*(ADDR_WIDTH)+:(ADDR_WIDTH)]), \
.P_PREFIX``dat_w(W_PREFIX``dat_w[(INDEX)*(DATA_WIDTH)+:(DATA_WIDTH)]), \
.P_PREFIX``dat_r(W_PREFIX``dat_r[(INDEX)*(DATA_WIDTH)+:(DATA_WIDTH)]), \
.P_PREFIX``cyc(W_PREFIX``cyc[INDEX]), \
.P_PREFIX``err(W_PREFIX``err[INDEX]), \
.P_PREFIX``sel(W_PREFIX``sel[(INDEX)*(DATA_WIDTH/8)+:(DATA_WIDTH/8)]), \
.P_PREFIX``stb(W_PREFIX``stb[INDEX]), \
.P_PREFIX``ack(W_PREFIX``ack[INDEX]), \
.P_PREFIX``we(W_PREFIX``we[INDEX])
`define WB_WIRES_ARR(PREFIX,ADDR_WIDTH,DATA_WIDTH,SIZE) \
wire[(SIZE*ADDR_WIDTH)-1:0] PREFIX``adr; \
wire[(SIZE*DATA_WIDTH)-1:0] PREFIX``dat_w; \
wire[(SIZE*DATA_WIDTH)-1:0] PREFIX``dat_r; \
wire[SIZE-1:0] PREFIX``cyc; \
wire[SIZE-1:0] PREFIX``err; \
wire[SIZE*(DATA_WIDTH/8)-1:0] PREFIX``sel; \
wire[SIZE-1:0] PREFIX``stb; \
wire[SIZE-1:0] PREFIX``ack; \
wire[SIZE-1:0] PREFIX``we
`ifndef MPRJ_IO_PADS
`define MPRJ_IO_PADS 38
`endif
/**
* Module: fwpayload
*
* Payload to go in Caravel
*
* - For simplicity, the IO's by and large mirror those of the user_project_wrapper
*/
module fwpayload(
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,
// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oen,
// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb
);
// Clock/reset control
// Allow the logic analyzer to take control of clock/reset
wire clk = (~la_oen[127]) ? la_data_in[127]: wb_clk_i;
wire rst = (~la_oen[126]) ? ~la_data_in[126]: wb_rst_i;
wire core_rst = (~la_oen[125]) ? ~la_data_in[125]: wb_rst_i;
/****************************************************************
* Interconnect definitions
****************************************************************/
// System interconnect
localparam N_INITIATORS = 3;
localparam INIT_ID_CORE_I = 0;
localparam INIT_ID_CORE_D = 1;
localparam INIT_ID_MGMT = 2;
`WB_WIRES_ARR(i_ic_,32,32,N_INITIATORS);
localparam N_TARGETS = 4;
localparam TGT_ID_SRAM = 0;
localparam TGT_ID_SPI = 1;
localparam TGT_ID_UART = 2;
localparam TGT_ID_GPIO = 3;
`WB_WIRES_ARR(ic_t_,32,32,N_TARGETS);
// Memory map
//
// 28-bit address space, with the upper 4 bits masked
//
// 0x00000000..0x00000FFFF - Program/data memory
// 0x01000000..0x010000000 - UART
// 0x01000000..0x010000100 - SPI
// 0x01000000..0x010000200 - GPIO
// Interconnect
wb_interconnect_NxN #(
.WB_ADDR_WIDTH(32),
.WB_DATA_WIDTH(32),
.N_INITIATORS(N_INITIATORS),
.N_TARGETS(N_TARGETS),
.I_ADR_MASK({
{ 32'h0F00_0000 },
{ 32'h0FFF_FF00 },
{ 32'h0FFF_FF00 },
{ 32'h0FFF_FF00 }
}),
.T_ADR({
{ 32'h0000_0000 },
{ 32'h0100_0000 },
{ 32'h0100_0100 },
{ 32'h0100_0200 }
})
) u_ic (
.clock(clk),
.reset(rst),
`WB_CONNECT(,i_ic_),
`WB_CONNECT(t,ic_t_)
);
/****************************************************************
* Connect management interface to port 1 on the interconnect
****************************************************************/
assign i_ic_adr[32*INIT_ID_MGMT+:32] = wbs_adr_i;
assign i_ic_dat_w[32*INIT_ID_MGMT+:32] = wbs_dat_i;
assign wbs_dat_o = i_ic_dat_r[32*INIT_ID_MGMT+:32];
assign i_ic_cyc[INIT_ID_MGMT] = wbs_cyc_i;
assign i_ic_sel[4*INIT_ID_MGMT+:4] = wbs_sel_i;
assign i_ic_stb[INIT_ID_MGMT] = wbs_stb_i;
assign wbs_ack_o = i_ic_ack[INIT_ID_MGMT];
assign i_ic_we[INIT_ID_MGMT] = wbs_we_i;
/****************************************************************
* FWRISC instance
****************************************************************/
fwrisc_rv32i_wb u_core (
.clock(clk),
.reset(core_rst),
`WB_CONNECT_ARR(wbi_,i_ic_,INIT_ID_CORE_I,32,32),
`WB_CONNECT_ARR(wbd_,i_ic_,INIT_ID_CORE_D,32,32)
);
// Probes
// - PC
// - [31:0] input
// - instr_complete
// - [32] input
// - gpio_out
// - [39:36] input
// - Clock and reset
// - 127 output - clock
// - 126 output - reset
// - 125 output - core_reset
localparam LA_CLOCK = 127;
localparam LA_RESET_SYS = 126;
localparam LA_RESET_CORE = 125;
localparam LA_GPIO_IN = 40;
localparam LA_GPIO_OUT = 36;
localparam LA_UART_RX = 34;
localparam LA_UART_TX = 33;
localparam LA_INSTR_COMPLETE = 32;
localparam LA_PC = 0;
wire[31:0] pc_probe = u_core.u_core.u_core.pc;
assign la_data_out[127:40] = 0;
assign la_data_out[35:33] = 0;
assign la_data_out[LA_PC+:32] = pc_probe;
assign la_data_out[LA_INSTR_COMPLETE] = u_core.u_core.u_core.instr_complete;
/****************************************************************
* Simple WB to SRAM bridge
****************************************************************/
reg[1:0] wb_bridge_state = 0;
wire[31:0] sram_adr_i = ic_t_adr[32*TGT_ID_SRAM+:32];
wire[31:0] sram_dat_w = ic_t_dat_w[32*TGT_ID_SRAM+:32];
wire[31:0] sram_dat_r;
assign ic_t_dat_r[32*TGT_ID_SRAM+:32] = sram_dat_r;
wire sram_cyc_i = ic_t_cyc[TGT_ID_SRAM];
assign ic_t_err[TGT_ID_SRAM] = 0;
wire[3:0] sram_sel_i = ic_t_sel[4*TGT_ID_SRAM+:4];
wire sram_stb_i = ic_t_stb[TGT_ID_SRAM];
wire sram_ack_o;
assign ic_t_ack[TGT_ID_SRAM] = sram_ack_o;
wire sram_we_i = ic_t_we[TGT_ID_SRAM];
always @(posedge clk) begin
if (rst == 1) begin
wb_bridge_state <= 0;
end else begin
case (wb_bridge_state)
0:
if (sram_cyc_i && sram_stb_i) begin
wb_bridge_state <= 1;
end
1:
wb_bridge_state <= 2;
2:
wb_bridge_state <= 3;
3:
wb_bridge_state <= 0;
default:
wb_bridge_state <= 0;
endcase
end
end
/****************************************************************
* SRAM
****************************************************************/
spram_32x256 u_sram(
.clock(clk),
.a_adr(sram_adr_i),
.a_dat_i(sram_dat_w),
.a_dat_o(sram_dat_r),
.a_we(sram_we_i),
.a_sel(sram_sel_i));
assign sram_ack_o = (wb_bridge_state == 3);
/****************************************************************
* External interfaces
****************************************************************/
// - UART
wire uart_enabled;
wire ser_tx;
wire ser_rx;
simpleuart_wb #(
.BASE_ADR(32'h0000_0000)
) u_uart (
.wb_clk_i(clk),
.wb_rst_i(rst),
.wb_adr_i({24'b0, ic_t_adr[32*TGT_ID_UART+:8]}),
.wb_dat_i(ic_t_dat_w[32*TGT_ID_UART+:32]),
.wb_sel_i(ic_t_sel[4*TGT_ID_UART+:4]),
.wb_we_i(ic_t_we[TGT_ID_UART]),
.wb_cyc_i(ic_t_cyc[TGT_ID_UART]),
.wb_stb_i(ic_t_stb[TGT_ID_UART]),
.wb_ack_o(ic_t_ack[TGT_ID_UART]),
.wb_dat_o(ic_t_dat_r[32*TGT_ID_UART+:32]),
.uart_enabled(uart_enabled),
.ser_tx(ser_tx),
.ser_rx(ser_rx)
);
assign ic_t_err[TGT_ID_UART] = 0;
// - SPI
wire hk_connect;
wire sdi;
wire csb;
wire sck;
wire sdo;
wire sdoenb;
wire irq;
simple_spi_master_wb #(
.BASE_ADR(32'h0000_0000)
) u_spi (
.wb_clk_i(clk),
.wb_rst_i(rst),
.wb_adr_i({24'b0, ic_t_adr[32*TGT_ID_SPI+:8]}),
.wb_dat_i(ic_t_dat_w[32*TGT_ID_SPI+:32]),
.wb_sel_i(ic_t_sel[4*TGT_ID_SPI+:4]),
.wb_we_i(ic_t_we[TGT_ID_SPI]),
.wb_cyc_i(ic_t_cyc[TGT_ID_SPI]),
.wb_stb_i(ic_t_stb[TGT_ID_SPI]),
.wb_ack_o(ic_t_ack[TGT_ID_SPI]),
.wb_dat_o(ic_t_dat_r[32*TGT_ID_SPI+:32]),
.hk_connect(hk_connect),
.sdi(sdi),
.csb(csb),
.sck(sck),
.sdo(sdo),
.sdoenb(sdoenb),
.irq(irq)
);
assign ic_t_err[TGT_ID_SPI] = 0;
// - Simple GPIO
reg[7:0] gpio_out;
wire[7:0] gpio_in;
wire[31:0] gpio_adr_i = ic_t_adr[32*TGT_ID_GPIO+:32];
wire[31:0] gpio_dat_w = ic_t_dat_w[32*TGT_ID_GPIO+:32];
wire[31:0] gpio_dat_r = {16'b0, gpio_in, gpio_out};
assign ic_t_dat_r[32*TGT_ID_GPIO+:32] = gpio_dat_r;
wire gpio_cyc_i = ic_t_cyc[TGT_ID_GPIO];
assign ic_t_err[TGT_ID_GPIO] = 0;
wire[3:0] gpio_sel_i = ic_t_sel[4*TGT_ID_GPIO+:4];
wire gpio_stb_i = ic_t_stb[TGT_ID_GPIO];
reg gpio_ack_o;
assign ic_t_ack[TGT_ID_GPIO] = gpio_ack_o;
wire gpio_we_i = ic_t_we[TGT_ID_GPIO];
always @(posedge clk) begin
if (rst == 1) begin
gpio_ack_o <= 1'b0;
gpio_out <= 8'b0;
end else begin
gpio_ack_o <= (gpio_cyc_i && gpio_stb_i);
if (gpio_cyc_i && gpio_stb_i && gpio_we_i) begin
gpio_out <= gpio_dat_w[7:0];
end
end
end
/****************************************************************
* Outputs
****************************************************************/
// Tie unused pins
assign io_out[11:0] = {12{1'b0}};
assign io_oeb[11:0] = {12{1'b0}};
// GPIO-o
assign io_out[15:12] = gpio_out[3:0];
assign io_oeb[15:12] = 4'hf;
// UART
assign io_out[16] = ser_tx;
assign io_oeb[16] = 1;
assign ser_rx = (~la_oen[LA_UART_RX])?la_data_in[LA_UART_RX]:io_in[17];
assign io_oeb[17] = 0;
assign sdi = io_in[18];
assign io_oeb[18] = 0;
assign io_out[19] = csb;
assign io_oeb[19] = 1;
assign io_out[20] = sck;
assign io_oeb[20] = 1;
assign io_out[21] = sdo;
assign io_oeb[21] = 1;
assign io_out[22] = sdoenb;
assign io_oeb[22] = 1;
// GPIO
assign io_out[26:23] = gpio_out[7:4];
assign io_oeb[26:23] = 4'hf;
assign gpio_in[0] = (~la_oen[LA_GPIO_IN])?la_data_in[LA_GPIO_IN]:io_in[27+0];
assign gpio_in[1] = (~la_oen[LA_GPIO_IN+1])?la_data_in[LA_GPIO_IN+1]:io_in[27+1];
assign gpio_in[2] = (~la_oen[LA_GPIO_IN+2])?la_data_in[LA_GPIO_IN+2]:io_in[27+2];
assign gpio_in[3] = (~la_oen[LA_GPIO_IN+3])?la_data_in[LA_GPIO_IN+3]:io_in[27+3];
assign gpio_in[7:4] = io_in[34:31];
assign io_oeb[34:27] = 4'h0;
// Unused
assign io_out[37:35] = {3{1'b0}};
assign io_oeb[37:35] = {3{1'b0}};
// Logic Analyzer I/O connections
// Probe the low bits of GPIO output with the LA
assign la_data_out[LA_GPIO_OUT+:4] = gpio_out[3:0];
assign gpio_in[3:0] = la_data_in[LA_GPIO_IN+:4];
assign la_data_out[LA_UART_TX] = ser_tx;
endmodule