newStep.v
This commit is contained in:
305
RTL/femtosoc_icestick_mecrisp_quintus.v
Normal file
305
RTL/femtosoc_icestick_mecrisp_quintus.v
Normal file
@@ -0,0 +1,305 @@
|
||||
// Special version of femtosoc for mecrisp-quintus (Forth interpreter) on IceStick, by Matthias Koch
|
||||
// mecrisp website: http://mecrisp.sourceforge.net/
|
||||
|
||||
`default_nettype none // Makes it easier to detect typos !
|
||||
|
||||
`define NRV_MINIRV32 // Mini config, can execute code stored in SPI flash from 1Mb offset (mapped to address 0x800000)
|
||||
`define NRV_RUN_FROM_SPI_FLASH // Running code from the SPI flash (changes the constant for delay loops)
|
||||
`define NRV_RESET_ADDR 24'h810000 // Directly jump into mapped SPI Flash,
|
||||
`define NRV_COUNTER_WIDTH 32 // Number of bits in click counter
|
||||
|
||||
`include "PROCESSOR/femtorv32_quark.v" // Minimalistic version of the processor
|
||||
`include "DEVICES/uart_picosoc_shrunk.v"
|
||||
`include "DEVICES/MappedSPIFlash.v"
|
||||
|
||||
module femtosoc(
|
||||
input oscillator,
|
||||
|
||||
output D1, D2, D3, D4, D5,
|
||||
|
||||
output TXD,
|
||||
input RXD,
|
||||
|
||||
output spi_clk,
|
||||
output spi_cs_n,
|
||||
inout spi_mosi,
|
||||
inout spi_miso,
|
||||
|
||||
// input IR_RX,
|
||||
// output IR_TX,
|
||||
// output IR_SD,
|
||||
|
||||
inout PIO1_02, // PMOD 1
|
||||
inout PIO1_03, // PMOD 2
|
||||
inout PIO1_04, // PMOD 3
|
||||
inout PIO1_05, // PMOD 4
|
||||
inout PIO1_06, // PMOD 5
|
||||
inout PIO1_07, // PMOD 6
|
||||
inout PIO1_08, // PMOD 7
|
||||
inout PIO1_09, // PMOD 8
|
||||
|
||||
inout PIO0_02, // Header 1
|
||||
inout PIO0_03, // Header 2
|
||||
inout PIO0_04, // Header 3
|
||||
inout PIO0_05, // Header 4
|
||||
inout PIO0_06, // Header 5
|
||||
inout PIO0_07, // Header 6
|
||||
inout PIO0_08, // Header 7
|
||||
inout PIO0_09, // Header 8
|
||||
|
||||
inout PIO2_10, // Header 1
|
||||
inout PIO2_11, // Header 2
|
||||
inout PIO2_12, // Header 3
|
||||
inout PIO2_13, // Header 4
|
||||
inout PIO2_14, // Header 5
|
||||
inout PIO2_15, // Header 6
|
||||
inout PIO2_16, // Header 7
|
||||
inout PIO2_17, // Header 8
|
||||
|
||||
input reset_button
|
||||
);
|
||||
|
||||
// ###### Clock #########################################
|
||||
|
||||
wire clk; // Configured for 48 MHz
|
||||
|
||||
SB_PLL40_CORE #(.FEEDBACK_PATH("SIMPLE"),
|
||||
.PLLOUT_SELECT("GENCLK"),
|
||||
.DIVR(4'b0000),
|
||||
.DIVF(7'b0111111),
|
||||
.DIVQ(3'b100),
|
||||
.FILTER_RANGE(3'b001),
|
||||
) uut (
|
||||
.REFERENCECLK(oscillator),
|
||||
.PLLOUTCORE(clk),
|
||||
.RESETB(1'b1),
|
||||
.BYPASS(1'b0)
|
||||
);
|
||||
|
||||
// ###### Reset logic ###################################
|
||||
|
||||
reg [7:0] reset_cnt = 0;
|
||||
wire resetq = &reset_cnt;
|
||||
|
||||
always @(posedge clk, negedge reset_button) begin
|
||||
if (!reset_button) reset_cnt <= 0;
|
||||
else reset_cnt <= reset_cnt + !resetq;
|
||||
end
|
||||
|
||||
// ###### Cycle counter #################################
|
||||
|
||||
//reg [31:0] cycles;
|
||||
//always @(posedge clk) cycles <= cycles + 1;
|
||||
|
||||
|
||||
// ###### LEDS ##########################################
|
||||
|
||||
reg [4:0] LEDs;
|
||||
assign {D5,D4,D3,D2,D1} = LEDs;
|
||||
|
||||
|
||||
// ###### RING OSCILLATOR ###############################
|
||||
|
||||
wire [1:0] buffers_in, buffers_out;
|
||||
assign buffers_in = {buffers_out[0:0], ~buffers_out[1]};
|
||||
SB_LUT4 #(
|
||||
.LUT_INIT(16'd2)
|
||||
) buffers [1:0] (
|
||||
.O(buffers_out),
|
||||
.I0(buffers_in),
|
||||
.I1(1'b0),
|
||||
.I2(1'b0),
|
||||
.I3(1'b0)
|
||||
);
|
||||
|
||||
wire random = ~buffers_out[1];
|
||||
|
||||
// ###### GPIO ##########################################
|
||||
|
||||
wire [24:0] port_in;
|
||||
reg [23:0] port_out;
|
||||
reg [23:0] port_dir;
|
||||
|
||||
assign port_in[24] = random;
|
||||
|
||||
// PMOD
|
||||
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio0 (.PACKAGE_PIN(PIO1_02), .D_OUT_0(port_out[ 0]), .D_IN_0(port_in[ 0]), .OUTPUT_ENABLE(port_dir[ 0]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio1 (.PACKAGE_PIN(PIO1_03), .D_OUT_0(port_out[ 1]), .D_IN_0(port_in[ 1]), .OUTPUT_ENABLE(port_dir[ 1]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio2 (.PACKAGE_PIN(PIO1_04), .D_OUT_0(port_out[ 2]), .D_IN_0(port_in[ 2]), .OUTPUT_ENABLE(port_dir[ 2]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio3 (.PACKAGE_PIN(PIO1_05), .D_OUT_0(port_out[ 3]), .D_IN_0(port_in[ 3]), .OUTPUT_ENABLE(port_dir[ 3]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio4 (.PACKAGE_PIN(PIO1_06), .D_OUT_0(port_out[ 4]), .D_IN_0(port_in[ 4]), .OUTPUT_ENABLE(port_dir[ 4]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio5 (.PACKAGE_PIN(PIO1_07), .D_OUT_0(port_out[ 5]), .D_IN_0(port_in[ 5]), .OUTPUT_ENABLE(port_dir[ 5]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio6 (.PACKAGE_PIN(PIO1_08), .D_OUT_0(port_out[ 6]), .D_IN_0(port_in[ 6]), .OUTPUT_ENABLE(port_dir[ 6]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) fio7 (.PACKAGE_PIN(PIO1_09), .D_OUT_0(port_out[ 7]), .D_IN_0(port_in[ 7]), .OUTPUT_ENABLE(port_dir[ 7]));
|
||||
|
||||
// Header 1
|
||||
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio0 (.PACKAGE_PIN(PIO0_02), .D_OUT_0(port_out[ 8]), .D_IN_0(port_in[ 8]), .OUTPUT_ENABLE(port_dir[ 8]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio1 (.PACKAGE_PIN(PIO0_03), .D_OUT_0(port_out[ 9]), .D_IN_0(port_in[ 9]), .OUTPUT_ENABLE(port_dir[ 9]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio2 (.PACKAGE_PIN(PIO0_04), .D_OUT_0(port_out[10]), .D_IN_0(port_in[10]), .OUTPUT_ENABLE(port_dir[10]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio3 (.PACKAGE_PIN(PIO0_05), .D_OUT_0(port_out[11]), .D_IN_0(port_in[11]), .OUTPUT_ENABLE(port_dir[11]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio4 (.PACKAGE_PIN(PIO0_06), .D_OUT_0(port_out[12]), .D_IN_0(port_in[12]), .OUTPUT_ENABLE(port_dir[12]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio5 (.PACKAGE_PIN(PIO0_07), .D_OUT_0(port_out[13]), .D_IN_0(port_in[13]), .OUTPUT_ENABLE(port_dir[13]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio6 (.PACKAGE_PIN(PIO0_08), .D_OUT_0(port_out[14]), .D_IN_0(port_in[14]), .OUTPUT_ENABLE(port_dir[14]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) gio7 (.PACKAGE_PIN(PIO0_09), .D_OUT_0(port_out[15]), .D_IN_0(port_in[15]), .OUTPUT_ENABLE(port_dir[15]));
|
||||
|
||||
// Header 2
|
||||
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio0 (.PACKAGE_PIN(PIO2_10), .D_OUT_0(port_out[16]), .D_IN_0(port_in[16]), .OUTPUT_ENABLE(port_dir[16]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio1 (.PACKAGE_PIN(PIO2_11), .D_OUT_0(port_out[17]), .D_IN_0(port_in[17]), .OUTPUT_ENABLE(port_dir[17]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio2 (.PACKAGE_PIN(PIO2_12), .D_OUT_0(port_out[18]), .D_IN_0(port_in[18]), .OUTPUT_ENABLE(port_dir[18]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio3 (.PACKAGE_PIN(PIO2_13), .D_OUT_0(port_out[19]), .D_IN_0(port_in[19]), .OUTPUT_ENABLE(port_dir[19]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio4 (.PACKAGE_PIN(PIO2_14), .D_OUT_0(port_out[20]), .D_IN_0(port_in[20]), .OUTPUT_ENABLE(port_dir[20]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio5 (.PACKAGE_PIN(PIO2_15), .D_OUT_0(port_out[21]), .D_IN_0(port_in[21]), .OUTPUT_ENABLE(port_dir[21]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio6 (.PACKAGE_PIN(PIO2_16), .D_OUT_0(port_out[22]), .D_IN_0(port_in[22]), .OUTPUT_ENABLE(port_dir[22]));
|
||||
SB_IO #(.PIN_TYPE(6'b1010_01)) hio7 (.PACKAGE_PIN(PIO2_17), .D_OUT_0(port_out[23]), .D_IN_0(port_in[23]), .OUTPUT_ENABLE(port_dir[23]));
|
||||
|
||||
|
||||
// ###### UART ##########################################
|
||||
|
||||
wire serial_valid, serial_busy;
|
||||
wire [7:0] serial_data;
|
||||
wire serial_wr = io_wstrb & io_word_address[IO_UART_DAT_bit];
|
||||
wire serial_rd = io_rstrb & io_word_address[IO_UART_DAT_bit];
|
||||
|
||||
buart #(
|
||||
.FREQ_MHZ(48),
|
||||
.BAUDS(115200)
|
||||
) the_buart (
|
||||
.clk(clk),
|
||||
.resetq(resetq),
|
||||
.rx(RXD),
|
||||
.tx(TXD),
|
||||
.rd(serial_rd),
|
||||
.wr(serial_wr),
|
||||
.valid(serial_valid),
|
||||
.busy(serial_busy),
|
||||
.tx_data(io_wdata[7:0]),
|
||||
.rx_data(serial_data)
|
||||
);
|
||||
|
||||
|
||||
// ###### IO PORTS ######################################
|
||||
|
||||
// We got a total of 20 bits for 1-hot addressing of IO registers.
|
||||
|
||||
localparam IO_LEDS_bit = 0; // RW four leds
|
||||
localparam IO_UART_DAT_bit = 1; // RW write: data to send (8 bits) read: received data (8 bits)
|
||||
localparam IO_UART_CNTL_bit = 2; // R status. bit 8: valid read data. bit 9: busy sending
|
||||
|
||||
localparam IO_PORT_IN_bit = 3; // R: GPIO port in
|
||||
localparam IO_PORT_OUT_bit = 4; // RW: GPIO port out
|
||||
localparam IO_PORT_DIR_bit = 5; // RW: GPIO port dir
|
||||
|
||||
// localparam IO_CYCLES_bit = 6;
|
||||
|
||||
assign io_rdata =
|
||||
|
||||
(io_word_address[IO_UART_DAT_bit ] ? {22'd0, serial_busy, serial_valid, serial_data} : 32'd0) |
|
||||
(io_word_address[IO_UART_CNTL_bit] ? {22'd0, serial_busy, serial_valid, serial_data} : 32'd0) |
|
||||
(io_word_address[IO_PORT_IN_bit] ? port_in : 32'd0) |
|
||||
(io_word_address[IO_PORT_OUT_bit] ? port_out : 32'd0) |
|
||||
(io_word_address[IO_PORT_DIR_bit] ? port_dir : 32'd0) |
|
||||
// (io_word_address[IO_CYCLES_bit] ? cycles : 32'd0) |
|
||||
(io_word_address[IO_LEDS_bit] ? LEDs : 32'd0);
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (io_wstrb && io_word_address[IO_LEDS_bit]) LEDs <= io_wdata;
|
||||
if (io_wstrb && io_word_address[IO_PORT_OUT_bit]) port_out <= io_wdata;
|
||||
if (io_wstrb && io_word_address[IO_PORT_DIR_bit]) port_dir <= io_wdata;
|
||||
end
|
||||
|
||||
// For now, we got no device that has blocking reads or writes
|
||||
|
||||
assign io_rbusy = 0 ;
|
||||
assign io_wbusy = 0 ;
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
/*
|
||||
* Memory and memory interface
|
||||
* memory map:
|
||||
* address[21:2] RAM word address (4 Mb max).
|
||||
* address[23:22] 00: RAM
|
||||
* 01: IO page (1-hot) (starts at 0x400000)
|
||||
* 10: SPI Flash page (starts at 0x800000)
|
||||
*/
|
||||
|
||||
// The memory bus.
|
||||
wire [31:0] mem_address; // 24 bits are used internally. The two LSBs are ignored (using word addresses)
|
||||
wire [3:0] mem_wmask; // mem write mask and strobe /write Legal values are 000,0001,0010,0100,1000,0011,1100,1111
|
||||
wire [31:0] mem_rdata; // processor <- (mem and peripherals)
|
||||
wire [31:0] mem_wdata; // processor -> (mem and peripherals)
|
||||
wire mem_rstrb; // mem read strobe. Goes high to initiate memory read.
|
||||
wire mem_rbusy; // processor <- (mem and peripherals). Stays high until a read transfer is finished.
|
||||
wire mem_wbusy; // processor <- (mem and peripherals). Stays high until a write transfer is finished.
|
||||
|
||||
wire mem_wstrb = |mem_wmask; // mem write strobe, goes high to initiate memory write (deduced from wmask)
|
||||
|
||||
// IO bus.
|
||||
wire mem_address_is_ram = (mem_address[23:22] == 2'b00);
|
||||
wire mem_address_is_io = (mem_address[23:22] == 2'b01);
|
||||
wire mem_address_is_spi_flash = (mem_address[23:22] == 2'b10);
|
||||
wire mapped_spi_flash_rbusy;
|
||||
wire [31:0] mapped_spi_flash_rdata;
|
||||
|
||||
MappedSPIFlash mapped_spi_flash(
|
||||
.clk(clk),
|
||||
.rstrb(mem_rstrb && mem_address_is_spi_flash),
|
||||
.word_address(mem_address[21:2]),
|
||||
.rdata(mapped_spi_flash_rdata),
|
||||
.rbusy(mapped_spi_flash_rbusy),
|
||||
.CLK(spi_clk),
|
||||
.CS_N(spi_cs_n),
|
||||
.IO({spi_miso,spi_mosi})
|
||||
);
|
||||
|
||||
wire [31:0] io_rdata;
|
||||
wire [31:0] io_wdata = mem_wdata;
|
||||
wire io_rstrb = mem_rstrb && mem_address_is_io;
|
||||
wire io_wstrb = mem_wstrb && mem_address_is_io;
|
||||
wire [19:0] io_word_address = mem_address[21:2]; // word offset in io page
|
||||
wire io_rbusy;
|
||||
wire io_wbusy;
|
||||
|
||||
assign mem_rbusy = io_rbusy | mapped_spi_flash_rbusy ;
|
||||
assign mem_wbusy = io_wbusy;
|
||||
|
||||
wire [19:0] ram_word_address = mem_address[21:2];
|
||||
reg [31:0] RAM[(6144/4)-1:0];
|
||||
reg [31:0] ram_rdata;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(mem_address_is_ram) begin
|
||||
if(mem_wmask[0]) RAM[ram_word_address][ 7:0 ] <= mem_wdata[ 7:0 ];
|
||||
if(mem_wmask[1]) RAM[ram_word_address][15:8 ] <= mem_wdata[15:8 ];
|
||||
if(mem_wmask[2]) RAM[ram_word_address][23:16] <= mem_wdata[23:16];
|
||||
if(mem_wmask[3]) RAM[ram_word_address][31:24] <= mem_wdata[31:24];
|
||||
end
|
||||
ram_rdata <= RAM[ram_word_address];
|
||||
end
|
||||
|
||||
assign mem_rdata = mem_address_is_io ? io_rdata :
|
||||
mem_address_is_ram ? ram_rdata :
|
||||
mapped_spi_flash_rdata;
|
||||
|
||||
/****************************************************************/
|
||||
/* And last but not least, the processor */
|
||||
|
||||
FemtoRV32 #(
|
||||
.ADDR_WIDTH(24)
|
||||
) processor(
|
||||
.clk(clk),
|
||||
.mem_addr(mem_address),
|
||||
.mem_wdata(mem_wdata),
|
||||
.mem_wmask(mem_wmask),
|
||||
.mem_rdata(mem_rdata),
|
||||
.mem_rstrb(mem_rstrb),
|
||||
.mem_rbusy(mem_rbusy),
|
||||
.mem_wbusy(mem_wbusy),
|
||||
.reset(resetq)
|
||||
);
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user