/*
|
/*
|
* Copyright (c) 2018, Marcelo Samsoniuk
|
* Copyright (c) 2018, Marcelo Samsoniuk
|
* All rights reserved.
|
* All rights reserved.
|
*
|
*
|
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
*
|
*
|
* * Redistributions of source code must retain the above copyright notice, this
|
* * Redistributions of source code must retain the above copyright notice, this
|
* list of conditions and the following disclaimer.
|
* list of conditions and the following disclaimer.
|
*
|
*
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
*
|
*
|
* * Neither the name of the copyright holder nor the names of its
|
* * Neither the name of the copyright holder nor the names of its
|
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived from
|
* this software without specific prior written permission.
|
* this software without specific prior written permission.
|
*
|
*
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
*/
|
*/
|
|
|
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
`include "../rtl/config.vh"
|
`include "../rtl/config.vh"
|
|
|
module darksocv
|
module darksocv
|
(
|
(
|
input XCLK, // external clock
|
input XCLK, // external clock
|
input XRES, // external reset
|
input XRES, // external reset
|
|
|
input UART_RXD, // UART receive line
|
input UART_RXD, // UART receive line
|
output UART_TXD, // UART transmit line
|
output UART_TXD, // UART transmit line
|
|
|
output [3:0] LED, // on-board leds
|
output [3:0] LED, // on-board leds
|
output [3:0] DEBUG // osciloscope
|
output [3:0] DEBUG // osciloscope
|
);
|
);
|
|
|
// internal/external reset logic
|
// internal/external reset logic
|
|
|
reg [7:0] IRES = -1;
|
reg [7:0] IRES = -1;
|
|
|
`ifdef INVRES
|
`ifdef INVRES
|
always@(posedge XCLK) IRES <= XRES==0 ? -1 : IRES[7] ? IRES-1 : 0; // reset low
|
always@(posedge XCLK) IRES <= XRES==0 ? -1 : IRES[7] ? IRES-1 : 0; // reset low
|
`else
|
`else
|
always@(posedge XCLK) IRES <= XRES==1 ? -1 : IRES[7] ? IRES-1 : 0; // reset high
|
always@(posedge XCLK) IRES <= XRES==1 ? -1 : IRES[7] ? IRES-1 : 0; // reset high
|
`endif
|
`endif
|
|
|
// clock generator logic
|
// clock generator logic
|
|
|
`ifdef BOARD_CK_REF
|
`ifdef BOARD_CK_REF
|
|
|
//`define BOARD_CK (`BOARD_CK_REF * `BOARD_CK_MUL / `BOARD_CK_DIV)
|
//`define BOARD_CK (`BOARD_CK_REF * `BOARD_CK_MUL / `BOARD_CK_DIV)
|
|
|
wire LOCKED, CLKFB, CLK;
|
wire LOCKED, CLKFB, CLK;
|
|
|
// useful script to calculate MUL/DIV values:
|
// useful script to calculate MUL/DIV values:
|
//
|
//
|
// awk 'BEGIN { for(m=2;m<=32;m++) for(d=1;d<=32;d++) print 66.666*m/d,m,d }' | sort -n
|
// awk 'BEGIN { for(m=2;m<=32;m++) for(d=1;d<=32;d++) print 66.666*m/d,m,d }' | sort -n
|
//
|
//
|
// example: reference w/ 66MHz, m=19, d=13 and fx=97.4MHz. not so useful after I discovered
|
// example: reference w/ 66MHz, m=19, d=13 and fx=97.4MHz. not so useful after I discovered
|
// that my evaluation board already has external clock generator :D
|
// that my evaluation board already has external clock generator :D
|
|
|
`ifdef XILINX7CLK
|
`ifdef XILINX7CLK
|
|
|
MMCME2_BASE #(
|
MMCME2_BASE #(
|
.BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW)
|
.BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW)
|
.CLKFBOUT_MULT_F(`BOARD_CK_MUL), // Multiply value for all CLKOUT (2.000-64.000).
|
.CLKFBOUT_MULT_F(`BOARD_CK_MUL), // Multiply value for all CLKOUT (2.000-64.000).
|
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000).
|
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000).
|
.CLKIN1_PERIOD((1e9/`BOARD_CK_REF)), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
|
.CLKIN1_PERIOD((1e9/`BOARD_CK_REF)), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
|
// CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
|
// CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
|
.CLKOUT0_DIVIDE_F(`BOARD_CK_DIV), // Divide amount for CLKOUT0 (1.000-128.000).
|
.CLKOUT0_DIVIDE_F(`BOARD_CK_DIV), // Divide amount for CLKOUT0 (1.000-128.000).
|
.CLKOUT1_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT1_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT2_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT2_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT3_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT3_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT4_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT4_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT5_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT5_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT6_DIVIDE(`BOARD_CK_DIV),
|
.CLKOUT6_DIVIDE(`BOARD_CK_DIV),
|
// CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
|
// CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
|
.CLKOUT0_DUTY_CYCLE(0.5),
|
.CLKOUT0_DUTY_CYCLE(0.5),
|
.CLKOUT1_DUTY_CYCLE(0.5),
|
.CLKOUT1_DUTY_CYCLE(0.5),
|
.CLKOUT2_DUTY_CYCLE(0.5),
|
.CLKOUT2_DUTY_CYCLE(0.5),
|
.CLKOUT3_DUTY_CYCLE(0.5),
|
.CLKOUT3_DUTY_CYCLE(0.5),
|
.CLKOUT4_DUTY_CYCLE(0.5),
|
.CLKOUT4_DUTY_CYCLE(0.5),
|
.CLKOUT5_DUTY_CYCLE(0.5),
|
.CLKOUT5_DUTY_CYCLE(0.5),
|
.CLKOUT6_DUTY_CYCLE(0.5),
|
.CLKOUT6_DUTY_CYCLE(0.5),
|
// CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
|
// CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
|
.CLKOUT0_PHASE(0.0),
|
.CLKOUT0_PHASE(0.0),
|
.CLKOUT1_PHASE(0.0),
|
.CLKOUT1_PHASE(0.0),
|
.CLKOUT2_PHASE(0.0),
|
.CLKOUT2_PHASE(0.0),
|
.CLKOUT3_PHASE(0.0),
|
.CLKOUT3_PHASE(0.0),
|
.CLKOUT4_PHASE(0.0),
|
.CLKOUT4_PHASE(0.0),
|
.CLKOUT5_PHASE(0.0),
|
.CLKOUT5_PHASE(0.0),
|
.CLKOUT6_PHASE(0.0),
|
.CLKOUT6_PHASE(0.0),
|
.CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
|
.CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
|
.DIVCLK_DIVIDE(1), // Master division value (1-106)
|
.DIVCLK_DIVIDE(1), // Master division value (1-106)
|
.REF_JITTER1(0.0), // Reference input jitter in UI (0.000-0.999).
|
.REF_JITTER1(0.0), // Reference input jitter in UI (0.000-0.999).
|
.STARTUP_WAIT("TRUE") // Delays DONE until MMCM is locked (FALSE, TRUE)
|
.STARTUP_WAIT("TRUE") // Delays DONE until MMCM is locked (FALSE, TRUE)
|
)
|
)
|
MMCME2_BASE_inst (
|
MMCME2_BASE_inst (
|
// Clock Outputs: 1-bit (each) output: User configurable clock outputs
|
// Clock Outputs: 1-bit (each) output: User configurable clock outputs
|
.CLKOUT0(CLK), // 1-bit output: CLKOUT0
|
.CLKOUT0(CLK), // 1-bit output: CLKOUT0
|
//.CLKOUT0B(CLKOUT0B), // 1-bit output: Inverted CLKOUT0
|
//.CLKOUT0B(CLKOUT0B), // 1-bit output: Inverted CLKOUT0
|
//.CLKOUT1(CLKPWM), // 1-bit output: CLKOUT1
|
//.CLKOUT1(CLKPWM), // 1-bit output: CLKOUT1
|
//.CLKOUT1B(CLKOUT1B), // 1-bit output: Inverted CLKOUT1
|
//.CLKOUT1B(CLKOUT1B), // 1-bit output: Inverted CLKOUT1
|
//.CLKOUT2(CLKOUT2), // 1-bit output: CLKOUT2
|
//.CLKOUT2(CLKOUT2), // 1-bit output: CLKOUT2
|
//.CLKOUT2B(CLKOUT2B), // 1-bit output: Inverted CLKOUT2
|
//.CLKOUT2B(CLKOUT2B), // 1-bit output: Inverted CLKOUT2
|
//.CLKOUT3(CLKOUT3), // 1-bit output: CLKOUT3
|
//.CLKOUT3(CLKOUT3), // 1-bit output: CLKOUT3
|
//.CLKOUT3B(CLKOUT3B), // 1-bit output: Inverted CLKOUT3
|
//.CLKOUT3B(CLKOUT3B), // 1-bit output: Inverted CLKOUT3
|
//.CLKOUT4(CLKOUT4), // 1-bit output: CLKOUT4
|
//.CLKOUT4(CLKOUT4), // 1-bit output: CLKOUT4
|
//.CLKOUT5(CLKOUT5), // 1-bit output: CLKOUT5
|
//.CLKOUT5(CLKOUT5), // 1-bit output: CLKOUT5
|
//.CLKOUT6(CLKOUT6), // 1-bit output: CLKOUT6
|
//.CLKOUT6(CLKOUT6), // 1-bit output: CLKOUT6
|
// Feedback Clocks: 1-bit (each) output: Clock feedback ports
|
// Feedback Clocks: 1-bit (each) output: Clock feedback ports
|
.CLKFBOUT(CLKFB), // 1-bit output: Feedback clock
|
.CLKFBOUT(CLKFB), // 1-bit output: Feedback clock
|
//.CLKFBOUTB(CLKFBOUTB), // 1-bit output: Inverted CLKFBOUT
|
//.CLKFBOUTB(CLKFBOUTB), // 1-bit output: Inverted CLKFBOUT
|
// Status Ports: 1-bit (each) output: MMCM status ports
|
// Status Ports: 1-bit (each) output: MMCM status ports
|
.LOCKED(LOCKED), // 1-bit output: LOCK
|
.LOCKED(LOCKED), // 1-bit output: LOCK
|
// Clock Inputs: 1-bit (each) input: Clock input
|
// Clock Inputs: 1-bit (each) input: Clock input
|
.CLKIN1(XCLK), // 1-bit input: Clock
|
.CLKIN1(XCLK), // 1-bit input: Clock
|
// Control Ports: 1-bit (each) input: MMCM control ports
|
// Control Ports: 1-bit (each) input: MMCM control ports
|
.PWRDWN(1'b0), // 1-bit input: Power-down
|
.PWRDWN(1'b0), // 1-bit input: Power-down
|
.RST(IRES[7]), // 1-bit input: Reset
|
.RST(IRES[7]), // 1-bit input: Reset
|
// Feedback Clocks: 1-bit (each) input: Clock feedback ports
|
// Feedback Clocks: 1-bit (each) input: Clock feedback ports
|
.CLKFBIN(CLKFB) // 1-bit input: Feedback clock
|
.CLKFBIN(CLKFB) // 1-bit input: Feedback clock
|
);
|
);
|
|
|
`else
|
`else
|
|
|
DCM_SP #(
|
DCM_SP #(
|
.CLKDV_DIVIDE(2.0), // CLKDV divide value
|
.CLKDV_DIVIDE(2.0), // CLKDV divide value
|
// (1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8,9,10,11,12,13,14,15,16).
|
// (1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8,9,10,11,12,13,14,15,16).
|
.CLKFX_DIVIDE(`BOARD_CK_DIV), // Divide value on CLKFX outputs - D - (1-32)
|
.CLKFX_DIVIDE(`BOARD_CK_DIV), // Divide value on CLKFX outputs - D - (1-32)
|
.CLKFX_MULTIPLY(`BOARD_CK_MUL), // Multiply value on CLKFX outputs - M - (2-32)
|
.CLKFX_MULTIPLY(`BOARD_CK_MUL), // Multiply value on CLKFX outputs - M - (2-32)
|
.CLKIN_DIVIDE_BY_2("FALSE"), // CLKIN divide by two (TRUE/FALSE)
|
.CLKIN_DIVIDE_BY_2("FALSE"), // CLKIN divide by two (TRUE/FALSE)
|
.CLKIN_PERIOD((1e9/`BOARD_CK_REF)), // Input clock period specified in nS
|
.CLKIN_PERIOD((1e9/`BOARD_CK_REF)), // Input clock period specified in nS
|
.CLKOUT_PHASE_SHIFT("NONE"), // Output phase shift (NONE, FIXED, VARIABLE)
|
.CLKOUT_PHASE_SHIFT("NONE"), // Output phase shift (NONE, FIXED, VARIABLE)
|
.CLK_FEEDBACK("1X"), // Feedback source (NONE, 1X, 2X)
|
.CLK_FEEDBACK("1X"), // Feedback source (NONE, 1X, 2X)
|
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SYSTEM_SYNCHRNOUS or SOURCE_SYNCHRONOUS
|
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SYSTEM_SYNCHRNOUS or SOURCE_SYNCHRONOUS
|
.DFS_FREQUENCY_MODE("LOW"), // Unsupported - Do not change value
|
.DFS_FREQUENCY_MODE("LOW"), // Unsupported - Do not change value
|
.DLL_FREQUENCY_MODE("LOW"), // Unsupported - Do not change value
|
.DLL_FREQUENCY_MODE("LOW"), // Unsupported - Do not change value
|
.DSS_MODE("NONE"), // Unsupported - Do not change value
|
.DSS_MODE("NONE"), // Unsupported - Do not change value
|
.DUTY_CYCLE_CORRECTION("TRUE"), // Unsupported - Do not change value
|
.DUTY_CYCLE_CORRECTION("TRUE"), // Unsupported - Do not change value
|
.FACTORY_JF(16'hc080), // Unsupported - Do not change value
|
.FACTORY_JF(16'hc080), // Unsupported - Do not change value
|
.PHASE_SHIFT(0), // Amount of fixed phase shift (-255 to 255)
|
.PHASE_SHIFT(0), // Amount of fixed phase shift (-255 to 255)
|
.STARTUP_WAIT("FALSE") // Delay config DONE until DCM_SP LOCKED (TRUE/FALSE)
|
.STARTUP_WAIT("FALSE") // Delay config DONE until DCM_SP LOCKED (TRUE/FALSE)
|
)
|
)
|
DCM_SP_inst (
|
DCM_SP_inst (
|
//.CLK0(CLK0), // 1-bit output: 0 degree clock output
|
//.CLK0(CLK0), // 1-bit output: 0 degree clock output
|
//.CLK180(CLK180), // 1-bit output: 180 degree clock output
|
//.CLK180(CLK180), // 1-bit output: 180 degree clock output
|
//.CLK270(CLK270), // 1-bit output: 270 degree clock output
|
//.CLK270(CLK270), // 1-bit output: 270 degree clock output
|
//.CLK2X(CLK2X), // 1-bit output: 2X clock frequency clock output
|
//.CLK2X(CLK2X), // 1-bit output: 2X clock frequency clock output
|
//.CLK2X180(CLK2X180), // 1-bit output: 2X clock frequency, 180 degree clock output
|
//.CLK2X180(CLK2X180), // 1-bit output: 2X clock frequency, 180 degree clock output
|
//.CLK90(CLK90), // 1-bit output: 90 degree clock output
|
//.CLK90(CLK90), // 1-bit output: 90 degree clock output
|
//.CLKDV(CLKDV), // 1-bit output: Divided clock output
|
//.CLKDV(CLKDV), // 1-bit output: Divided clock output
|
.CLKFX(CLK), // 1-bit output: Digital Frequency Synthesizer output (DFS)
|
.CLKFX(CLK), // 1-bit output: Digital Frequency Synthesizer output (DFS)
|
//.CLKFX180(CLKFX180), // 1-bit output: 180 degree CLKFX output
|
//.CLKFX180(CLKFX180), // 1-bit output: 180 degree CLKFX output
|
.LOCKED(LOCKED), // 1-bit output: DCM_SP Lock Output
|
.LOCKED(LOCKED), // 1-bit output: DCM_SP Lock Output
|
//.PSDONE(PSDONE), // 1-bit output: Phase shift done output
|
//.PSDONE(PSDONE), // 1-bit output: Phase shift done output
|
//.STATUS(STATUS), // 8-bit output: DCM_SP status output
|
//.STATUS(STATUS), // 8-bit output: DCM_SP status output
|
//.CLKFB(CLKFB), // 1-bit input: Clock feedback input
|
//.CLKFB(CLKFB), // 1-bit input: Clock feedback input
|
.CLKIN(XCLK), // 1-bit input: Clock input
|
.CLKIN(XCLK), // 1-bit input: Clock input
|
//.DSSEN(DSSEN), // 1-bit input: Unsupported, specify to GND.
|
//.DSSEN(DSSEN), // 1-bit input: Unsupported, specify to GND.
|
//.PSCLK(PSCLK), // 1-bit input: Phase shift clock input
|
//.PSCLK(PSCLK), // 1-bit input: Phase shift clock input
|
.PSEN(1'b0), // 1-bit input: Phase shift enable
|
.PSEN(1'b0), // 1-bit input: Phase shift enable
|
//.PSINCDEC(PSINCDEC), // 1-bit input: Phase shift increment/decrement input
|
//.PSINCDEC(PSINCDEC), // 1-bit input: Phase shift increment/decrement input
|
.RST(IRES[7]) // 1-bit input: Active high reset input
|
.RST(IRES[7]) // 1-bit input: Active high reset input
|
);
|
);
|
|
|
`endif
|
`endif
|
|
|
reg [7:0] DRES = -1;
|
reg [7:0] DRES = -1;
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
DRES <= LOCKED==0 ? -1 : DRES ? DRES-1 : 0;
|
DRES <= LOCKED==0 ? -1 : DRES ? DRES-1 : 0;
|
end
|
end
|
|
|
wire RES = DRES[7];
|
wire RES = DRES[7];
|
|
|
`else
|
`else
|
|
|
// when there is no need for a clock generator:
|
// when there is no need for a clock generator:
|
|
|
wire CLK = XCLK;
|
wire CLK = XCLK;
|
wire RES = IRES[7];
|
wire RES = IRES[7];
|
`endif
|
`endif
|
// ro/rw memories
|
// ro/rw memories
|
|
|
`ifdef __HARVARD__
|
`ifdef __HARVARD__
|
|
|
reg [31:0] ROM [0:1023]; // ro memory
|
reg [31:0] ROM [0:1023]; // ro memory
|
reg [31:0] RAM [0:1023]; // rw memory
|
reg [31:0] RAM [0:1023]; // rw memory
|
|
|
// memory initialization
|
// memory initialization
|
|
|
integer i;
|
integer i;
|
initial
|
initial
|
begin
|
begin
|
for(i=0;i!=1024;i=i+1)
|
for(i=0;i!=1024;i=i+1)
|
begin
|
begin
|
ROM[i] = 32'd0;
|
ROM[i] = 32'd0;
|
RAM[i] = 32'd0;
|
RAM[i] = 32'd0;
|
end
|
end
|
|
|
// workaround for vivado: no path in simulation and .mem extension
|
// workaround for vivado: no path in simulation and .mem extension
|
|
|
`ifdef XILINX_SIMULATOR
|
`ifdef XILINX_SIMULATOR
|
$readmemh("darksocv.rom.mem",ROM);
|
$readmemh("darksocv.rom.mem",ROM);
|
$readmemh("darksocv.ram.mem",RAM);
|
$readmemh("darksocv.ram.mem",RAM);
|
`else
|
`else
|
$readmemh("../src/darksocv.rom.mem",ROM);
|
$readmemh("../src/darksocv.rom.mem",ROM);
|
$readmemh("../src/darksocv.ram.mem",RAM);
|
$readmemh("../src/darksocv.ram.mem",RAM);
|
`endif
|
`endif
|
end
|
end
|
|
|
`else
|
`else
|
|
|
reg [31:0] MEM [0:2047]; // ro memory
|
reg [31:0] MEM [0:2047]; // ro memory
|
|
|
// memory initialization
|
// memory initialization
|
|
|
integer i;
|
integer i;
|
initial
|
initial
|
begin
|
begin
|
for(i=0;i!=2048;i=i+1)
|
for(i=0;i!=2048;i=i+1)
|
begin
|
begin
|
MEM[i] = 32'd0;
|
MEM[i] = 32'd0;
|
end
|
end
|
|
|
// workaround for vivado: no path in simulation and .mem extension
|
// workaround for vivado: no path in simulation and .mem extension
|
|
|
`ifdef XILINX_SIMULATOR
|
`ifdef XILINX_SIMULATOR
|
$readmemh("darksocv.mem",MEM);
|
$readmemh("darksocv.mem",MEM);
|
`else
|
`else
|
$readmemh("../src/darksocv.mem",MEM);
|
$readmemh("../src/darksocv.mem",MEM);
|
`endif
|
`endif
|
end
|
end
|
|
|
`endif
|
`endif
|
|
|
// darkriscv bus interface
|
// darkriscv bus interface
|
|
|
wire [31:0] IADDR;
|
wire [31:0] IADDR;
|
wire [31:0] DADDR;
|
wire [31:0] DADDR;
|
wire [31:0] IDATA;
|
wire [31:0] IDATA;
|
wire [31:0] DATAO;
|
wire [31:0] DATAO;
|
wire [31:0] DATAI;
|
wire [31:0] DATAI;
|
wire WR,RD;
|
wire WR,RD;
|
wire [3:0] BE;
|
wire [3:0] BE;
|
|
|
`ifdef __FLEXBUZZ__
|
`ifdef __FLEXBUZZ__
|
wire [31:0] XATAO;
|
wire [31:0] XATAO;
|
wire [31:0] XATAI;
|
wire [31:0] XATAI;
|
wire [ 2:0] DLEN;
|
wire [ 2:0] DLEN;
|
wire RW;
|
wire RW;
|
`endif
|
`endif
|
|
|
wire [31:0] IOMUX [0:3];
|
wire [31:0] IOMUX [0:3];
|
|
|
reg [15:0] GPIOFF = 0;
|
reg [15:0] GPIOFF = 0;
|
reg [15:0] LEDFF = 0;
|
reg [15:0] LEDFF = 0;
|
|
|
wire HLT;
|
wire HLT;
|
|
|
`ifdef __ICACHE__
|
`ifdef __ICACHE__
|
|
|
// instruction cache
|
// instruction cache
|
|
|
reg [55:0] ICACHE [0:63]; // instruction cache
|
reg [55:0] ICACHE [0:63]; // instruction cache
|
reg [63:0] ITAG = 0; // instruction cache tag
|
reg [63:0] ITAG = 0; // instruction cache tag
|
|
|
wire [5:0] IPTR = IADDR[7:2];
|
wire [5:0] IPTR = IADDR[7:2];
|
wire [55:0] ICACHEO = ICACHE[IPTR];
|
wire [55:0] ICACHEO = ICACHE[IPTR];
|
wire [31:0] ICACHED = ICACHEO[31: 0]; // data
|
wire [31:0] ICACHED = ICACHEO[31: 0]; // data
|
wire [31:8] ICACHEA = ICACHEO[55:32]; // address
|
wire [31:8] ICACHEA = ICACHEO[55:32]; // address
|
|
|
wire IHIT = ITAG[IPTR] && ICACHEA==IADDR[31:8];
|
wire IHIT = ITAG[IPTR] && ICACHEA==IADDR[31:8];
|
|
|
reg IFFX = 0;
|
reg IFFX = 0;
|
reg IFFX2 = 0;
|
reg IFFX2 = 0;
|
|
|
reg [31:0] ROMFF;
|
reg [31:0] ROMFF;
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
ROMFF <= ROM[IADDR[11:2]];
|
ROMFF <= ROM[IADDR[11:2]];
|
|
|
if(IFFX2)
|
if(IFFX2)
|
begin
|
begin
|
IFFX2 <= 0;
|
IFFX2 <= 0;
|
IFFX <= 0;
|
IFFX <= 0;
|
end
|
end
|
else
|
else
|
if(!IHIT)
|
if(!IHIT)
|
begin
|
begin
|
ICACHE[IPTR] <= { IADDR[31:8], ROMFF };
|
ICACHE[IPTR] <= { IADDR[31:8], ROMFF };
|
ITAG[IPTR] <= IFFX; // cached!
|
ITAG[IPTR] <= IFFX; // cached!
|
IFFX <= 1;
|
IFFX <= 1;
|
IFFX2 <= IFFX;
|
IFFX2 <= IFFX;
|
end
|
end
|
end
|
end
|
|
|
assign IDATA = ICACHED;
|
assign IDATA = ICACHED;
|
|
|
`else
|
`else
|
|
|
reg [31:0] ROMFF;
|
reg [31:0] ROMFF;
|
|
|
`ifdef __WAITSTATES__
|
`ifdef __WAITSTATES__
|
|
|
reg [1:0] IHITACK = 0;
|
reg [1:0] IHITACK = 0;
|
|
|
wire IHIT = !(IHITACK!=1);
|
wire IHIT = !(IHITACK!=1);
|
|
|
always@(posedge CLK) // stage #1.0
|
always@(posedge CLK) // stage #1.0
|
begin
|
begin
|
IHITACK <= RES ? 1 : IHITACK ? IHITACK-1 : 1; // wait-states
|
IHITACK <= RES ? 1 : IHITACK ? IHITACK-1 : 1; // wait-states
|
end
|
end
|
`else
|
`else
|
|
|
wire IHIT = 1;
|
wire IHIT = 1;
|
|
|
`endif
|
`endif
|
|
|
|
|
`ifdef __3STAGE__
|
`ifdef __3STAGE__
|
|
|
reg [31:0] ROMFF2 = 0;
|
reg [31:0] ROMFF2 = 0;
|
reg HLT2 = 0;
|
reg HLT2 = 0;
|
|
|
always@(posedge CLK) // stage #0.5
|
always@(posedge CLK) // stage #0.5
|
begin
|
begin
|
if(HLT)
|
if(HLT)
|
begin
|
begin
|
ROMFF2 <= ROMFF;
|
ROMFF2 <= ROMFF;
|
end
|
end
|
|
|
HLT2 <= HLT;
|
HLT2 <= HLT;
|
end
|
end
|
|
|
assign IDATA = HLT2 ? ROMFF2 : ROMFF;
|
assign IDATA = HLT2 ? ROMFF2 : ROMFF;
|
`else
|
`else
|
assign IDATA = ROMFF;
|
assign IDATA = ROMFF;
|
`endif
|
`endif
|
|
|
always@(posedge CLK) // stage #0.5
|
always@(posedge CLK) // stage #0.5
|
begin
|
begin
|
`ifdef __HARVARD__
|
`ifdef __HARVARD__
|
ROMFF <= ROM[IADDR[11:2]];
|
ROMFF <= ROM[IADDR[11:2]];
|
`else
|
`else
|
ROMFF <= MEM[IADDR[12:2]];
|
ROMFF <= MEM[IADDR[12:2]];
|
`endif
|
`endif
|
end
|
end
|
|
|
//assign IDATA = ROM[IADDR[11:2]];
|
//assign IDATA = ROM[IADDR[11:2]];
|
|
|
// always@(posedge CLK)
|
// always@(posedge CLK)
|
// begin
|
// begin
|
// // weird bug appears to be related to the "sw ra,12(sp)" instruction.
|
// // weird bug appears to be related to the "sw ra,12(sp)" instruction.
|
// if(WR&&DADDR[31]==0&&DADDR[12]==0)
|
// if(WR&&DADDR[31]==0&&DADDR[12]==0)
|
// begin
|
// begin
|
// ROMBUG <= IADDR;
|
// ROMBUG <= IADDR;
|
// end
|
// end
|
// end
|
// end
|
|
|
// assign IDATA = ROMFF;
|
// assign IDATA = ROMFF;
|
|
|
`endif
|
`endif
|
|
|
`ifdef __DCACHE__
|
`ifdef __DCACHE__
|
|
|
// data cache
|
// data cache
|
|
|
reg [55:0] DCACHE [0:63]; // data cache
|
reg [55:0] DCACHE [0:63]; // data cache
|
reg [63:0] DTAG = 0; // data cache tag
|
reg [63:0] DTAG = 0; // data cache tag
|
|
|
wire [5:0] DPTR = DADDR[7:2];
|
wire [5:0] DPTR = DADDR[7:2];
|
wire [55:0] DCACHEO = DCACHE[DPTR];
|
wire [55:0] DCACHEO = DCACHE[DPTR];
|
wire [31:0] DCACHED = DCACHEO[31: 0]; // data
|
wire [31:0] DCACHED = DCACHEO[31: 0]; // data
|
wire [31:8] DCACHEA = DCACHEO[55:32]; // address
|
wire [31:8] DCACHEA = DCACHEO[55:32]; // address
|
|
|
wire DHIT = RD&&!DADDR[31]/*&&DADDR[12]*/ ? DTAG[DPTR] && DCACHEA==DADDR[31:8] : 1;
|
wire DHIT = RD&&!DADDR[31]/*&&DADDR[12]*/ ? DTAG[DPTR] && DCACHEA==DADDR[31:8] : 1;
|
|
|
reg FFX = 0;
|
reg FFX = 0;
|
reg FFX2 = 0;
|
reg FFX2 = 0;
|
|
|
reg [31:0] RAMFF;
|
reg [31:0] RAMFF;
|
|
|
reg WTAG = 0;
|
reg WTAG = 0;
|
reg [31:0] WCACHEA = 0;
|
reg [31:0] WCACHEA = 0;
|
|
|
wire WHIT = WR&&!DADDR[31]/*&&DADDR[12]*/ ? WTAG&&WCACHEA==DADDR : 1;
|
wire WHIT = WR&&!DADDR[31]/*&&DADDR[12]*/ ? WTAG&&WCACHEA==DADDR : 1;
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
RAMFF <= RAM[DADDR[11:2]];
|
RAMFF <= RAM[DADDR[11:2]];
|
|
|
if(FFX2)
|
if(FFX2)
|
begin
|
begin
|
FFX2 <= 0;
|
FFX2 <= 0;
|
FFX <= 0;
|
FFX <= 0;
|
WCACHEA <= 0;
|
WCACHEA <= 0;
|
WTAG <= 0;
|
WTAG <= 0;
|
end
|
end
|
else
|
else
|
if(!WHIT)
|
if(!WHIT)
|
begin
|
begin
|
//individual byte/word/long selection, thanks to HYF!
|
//individual byte/word/long selection, thanks to HYF!
|
if(BE[0]) RAM[DADDR[11:2]][0 * 8 + 7: 0 * 8] <= DATAO[0 * 8 + 7: 0 * 8];
|
if(BE[0]) RAM[DADDR[11:2]][0 * 8 + 7: 0 * 8] <= DATAO[0 * 8 + 7: 0 * 8];
|
if(BE[1]) RAM[DADDR[11:2]][1 * 8 + 7: 1 * 8] <= DATAO[1 * 8 + 7: 1 * 8];
|
if(BE[1]) RAM[DADDR[11:2]][1 * 8 + 7: 1 * 8] <= DATAO[1 * 8 + 7: 1 * 8];
|
if(BE[2]) RAM[DADDR[11:2]][2 * 8 + 7: 2 * 8] <= DATAO[2 * 8 + 7: 2 * 8];
|
if(BE[2]) RAM[DADDR[11:2]][2 * 8 + 7: 2 * 8] <= DATAO[2 * 8 + 7: 2 * 8];
|
if(BE[3]) RAM[DADDR[11:2]][3 * 8 + 7: 3 * 8] <= DATAO[3 * 8 + 7: 3 * 8];
|
if(BE[3]) RAM[DADDR[11:2]][3 * 8 + 7: 3 * 8] <= DATAO[3 * 8 + 7: 3 * 8];
|
|
|
DCACHE[DPTR][0 * 8 + 7: 0 * 8] <= BE[0] ? DATAO[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8];
|
DCACHE[DPTR][0 * 8 + 7: 0 * 8] <= BE[0] ? DATAO[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8];
|
DCACHE[DPTR][1 * 8 + 7: 1 * 8] <= BE[1] ? DATAO[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8];
|
DCACHE[DPTR][1 * 8 + 7: 1 * 8] <= BE[1] ? DATAO[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8];
|
DCACHE[DPTR][2 * 8 + 7: 2 * 8] <= BE[2] ? DATAO[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8];
|
DCACHE[DPTR][2 * 8 + 7: 2 * 8] <= BE[2] ? DATAO[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8];
|
DCACHE[DPTR][3 * 8 + 7: 3 * 8] <= BE[3] ? DATAO[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8];
|
DCACHE[DPTR][3 * 8 + 7: 3 * 8] <= BE[3] ? DATAO[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8];
|
|
|
DCACHE[DPTR][55:32] <= DADDR[31:8];
|
DCACHE[DPTR][55:32] <= DADDR[31:8];
|
|
|
//DCACHE[DPTR] <= { DADDR[31:8],
|
//DCACHE[DPTR] <= { DADDR[31:8],
|
// BE[3] ? DATAO[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8],
|
// BE[3] ? DATAO[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8],
|
// BE[2] ? DATAO[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8],
|
// BE[2] ? DATAO[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8],
|
// BE[1] ? DATAO[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8],
|
// BE[1] ? DATAO[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8],
|
// BE[0] ? DATAO[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8]
|
// BE[0] ? DATAO[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8]
|
// };
|
// };
|
|
|
DTAG[DPTR] <= FFX; // cached!
|
DTAG[DPTR] <= FFX; // cached!
|
WTAG <= FFX;
|
WTAG <= FFX;
|
|
|
WCACHEA <= DADDR;
|
WCACHEA <= DADDR;
|
|
|
FFX <= 1;
|
FFX <= 1;
|
FFX2 <= FFX;
|
FFX2 <= FFX;
|
end
|
end
|
else
|
else
|
if(!DHIT)
|
if(!DHIT)
|
begin
|
begin
|
DCACHE[DPTR] <= { DADDR[31:8], RAMFF };
|
DCACHE[DPTR] <= { DADDR[31:8], RAMFF };
|
DTAG[DPTR] <= FFX; // cached!
|
DTAG[DPTR] <= FFX; // cached!
|
FFX <= 1;
|
FFX <= 1;
|
FFX2 <= FFX;
|
FFX2 <= FFX;
|
end
|
end
|
end
|
end
|
|
|
assign DATAI = DADDR[31] ? IOMUX[DADDR[3:2]] : DCACHED;
|
assign DATAI = DADDR[31] ? IOMUX[DADDR[3:2]] : DCACHED;
|
|
|
`else
|
`else
|
|
|
// no cache!
|
// no cache!
|
|
|
`ifdef __FLEXBUZZ__
|
`ifdef __FLEXBUZZ__
|
|
|
// must work just exactly as the default interface, since we have no
|
// must work just exactly as the default interface, since we have no
|
// flexbuzz devices available yet (i.e., all devices are 32-bit now)
|
// flexbuzz devices available yet (i.e., all devices are 32-bit now)
|
|
|
assign XATAI = DLEN[0] ? ( DADDR[1:0]==3 ? DATAI[31:24] :
|
assign XATAI = DLEN[0] ? ( DADDR[1:0]==3 ? DATAI[31:24] :
|
DADDR[1:0]==2 ? DATAI[23:16] :
|
DADDR[1:0]==2 ? DATAI[23:16] :
|
DADDR[1:0]==1 ? DATAI[15: 8] :
|
DADDR[1:0]==1 ? DATAI[15: 8] :
|
DATAI[ 7: 0] ):
|
DATAI[ 7: 0] ):
|
DLEN[1] ? ( DADDR[1]==1 ? DATAI[31:16] :
|
DLEN[1] ? ( DADDR[1]==1 ? DATAI[31:16] :
|
DATAI[15: 0] ):
|
DATAI[15: 0] ):
|
DATAI;
|
DATAI;
|
|
|
assign DATAO = DLEN[0] ? ( DADDR[1:0]==3 ? { XATAO[ 7: 0], 24'hx } :
|
assign DATAO = DLEN[0] ? ( DADDR[1:0]==3 ? { XATAO[ 7: 0], 24'hx } :
|
DADDR[1:0]==2 ? { 8'hx, XATAO[ 7: 0], 16'hx } :
|
DADDR[1:0]==2 ? { 8'hx, XATAO[ 7: 0], 16'hx } :
|
DADDR[1:0]==1 ? { 16'hx, XATAO[ 7: 0], 8'hx } :
|
DADDR[1:0]==1 ? { 16'hx, XATAO[ 7: 0], 8'hx } :
|
{ 24'hx, XATAO[ 7: 0] } ):
|
{ 24'hx, XATAO[ 7: 0] } ):
|
DLEN[1] ? ( DADDR[1]==1 ? { XATAO[15: 0], 16'hx } :
|
DLEN[1] ? ( DADDR[1]==1 ? { XATAO[15: 0], 16'hx } :
|
{ 16'hx, XATAO[15: 0] } ):
|
{ 16'hx, XATAO[15: 0] } ):
|
XATAO;
|
XATAO;
|
|
|
assign RD = DLEN&&RW==1;
|
assign RD = DLEN&&RW==1;
|
assign WR = DLEN&&RW==0;
|
assign WR = DLEN&&RW==0;
|
|
|
assign BE = DLEN[0] ? ( DADDR[1:0]==3 ? 4'b1000 : // 8-bit
|
assign BE = DLEN[0] ? ( DADDR[1:0]==3 ? 4'b1000 : // 8-bit
|
DADDR[1:0]==2 ? 4'b0100 :
|
DADDR[1:0]==2 ? 4'b0100 :
|
DADDR[1:0]==1 ? 4'b0010 :
|
DADDR[1:0]==1 ? 4'b0010 :
|
4'b0001 ) :
|
4'b0001 ) :
|
DLEN[1] ? ( DADDR[1]==1 ? 4'b1100 : // 16-bit
|
DLEN[1] ? ( DADDR[1]==1 ? 4'b1100 : // 16-bit
|
4'b0011 ) :
|
4'b0011 ) :
|
4'b1111; // 32-bit
|
4'b1111; // 32-bit
|
|
|
`endif
|
`endif
|
|
|
reg [31:0] RAMFF;
|
reg [31:0] RAMFF;
|
`ifdef __WAITSTATES__
|
`ifdef __WAITSTATES__
|
|
|
reg [1:0] DACK = 0;
|
reg [1:0] DACK = 0;
|
|
|
wire WHIT = 1;
|
wire WHIT = 1;
|
wire DHIT = !((WR||RD) && DACK!=1);
|
wire DHIT = !((WR||RD) && DACK!=1);
|
|
|
always@(posedge CLK) // stage #1.0
|
always@(posedge CLK) // stage #1.0
|
begin
|
begin
|
DACK <= RES ? 0 : DACK ? DACK-1 : (RD||WR) ? 1 : 0; // wait-states
|
DACK <= RES ? 0 : DACK ? DACK-1 : (RD||WR) ? 1 : 0; // wait-states
|
end
|
end
|
|
|
`elsif __3STAGE__
|
`elsif __3STAGE__
|
|
|
// for single phase clock: 1 wait state in read op always required!
|
// for single phase clock: 1 wait state in read op always required!
|
|
|
reg [1:0] DACK = 0;
|
reg [1:0] DACK = 0;
|
|
|
wire WHIT = 1;
|
wire WHIT = 1;
|
wire DHIT = !((RD||WR) && DACK!=1); // the WR operatio does not need ws. in this config.
|
wire DHIT = !((RD
|
|
`ifdef __RMW_CYCLE__
|
|
||WR // worst code ever! but it is 3:12am...
|
|
`endif
|
|
) && DACK!=1); // the WR operatio does not need ws. in this config.
|
|
|
always@(posedge CLK) // stage #1.0
|
always@(posedge CLK) // stage #1.0
|
begin
|
begin
|
DACK <= RES ? 0 : DACK ? DACK-1 : (RD||WR) ? 1 : 0; // wait-states
|
DACK <= RES ? 0 : DACK ? DACK-1 : (RD
|
|
`ifdef __RMW_CYCLE__
|
|
||WR // 2nd worst code ever!
|
|
`endif
|
|
) ? 1 : 0; // wait-states
|
end
|
end
|
|
|
`else
|
`else
|
|
|
// for dual phase clock: 0 wait state
|
// for dual phase clock: 0 wait state
|
|
|
wire WHIT = 1;
|
wire WHIT = 1;
|
wire DHIT = 1;
|
wire DHIT = 1;
|
|
|
`endif
|
`endif
|
|
|
always@(posedge CLK) // stage #1.5
|
always@(posedge CLK) // stage #1.5
|
begin
|
begin
|
`ifdef __HARVARD__
|
`ifdef __HARVARD__
|
RAMFF <= RAM[DADDR[11:2]];
|
RAMFF <= RAM[DADDR[11:2]];
|
`else
|
`else
|
RAMFF <= MEM[DADDR[12:2]];
|
RAMFF <= MEM[DADDR[12:2]];
|
`endif
|
`endif
|
end
|
end
|
|
|
//assign DATAI = DADDR[31] ? IOMUX : RAM[DADDR[11:2]];
|
//assign DATAI = DADDR[31] ? IOMUX : RAM[DADDR[11:2]];
|
|
|
reg [31:0] IOMUXFF;
|
reg [31:0] IOMUXFF;
|
|
|
//individual byte/word/long selection, thanks to HYF!
|
//individual byte/word/long selection, thanks to HYF!
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
|
|
`ifdef __3STAGE__
|
`ifdef __RMW_CYCLE__
|
|
|
// read-modify-write operation w/ 1 wait-state:
|
// read-modify-write operation w/ 1 wait-state:
|
|
|
if(!HLT&&WR&&DADDR[31]==0/*&&DADDR[12]==1*/)
|
if(!HLT&&WR&&DADDR[31]==0/*&&DADDR[12]==1*/)
|
begin
|
begin
|
`ifdef __HARVARD__
|
`ifdef __HARVARD__
|
RAM[DADDR[11:2]] <=
|
RAM[DADDR[11:2]] <=
|
`else
|
`else
|
MEM[DADDR[12:2]] <=
|
MEM[DADDR[12:2]] <=
|
`endif
|
`endif
|
{
|
{
|
BE[3] ? DATAO[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8],
|
BE[3] ? DATAO[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8],
|
BE[2] ? DATAO[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8],
|
BE[2] ? DATAO[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8],
|
BE[1] ? DATAO[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8],
|
BE[1] ? DATAO[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8],
|
BE[0] ? DATAO[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8]
|
BE[0] ? DATAO[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8]
|
};
|
};
|
end
|
end
|
|
|
`else
|
`else
|
// write-only operation w/ 0 wait-states:
|
// write-only operation w/ 0 wait-states:
|
`ifdef __HARVARD__
|
`ifdef __HARVARD__
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[3]) RAM[DADDR[11:2]][3 * 8 + 7: 3 * 8] <= DATAO[3 * 8 + 7: 3 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[3]) RAM[DADDR[11:2]][3 * 8 + 7: 3 * 8] <= DATAO[3 * 8 + 7: 3 * 8];
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[2]) RAM[DADDR[11:2]][2 * 8 + 7: 2 * 8] <= DATAO[2 * 8 + 7: 2 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[2]) RAM[DADDR[11:2]][2 * 8 + 7: 2 * 8] <= DATAO[2 * 8 + 7: 2 * 8];
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[1]) RAM[DADDR[11:2]][1 * 8 + 7: 1 * 8] <= DATAO[1 * 8 + 7: 1 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[1]) RAM[DADDR[11:2]][1 * 8 + 7: 1 * 8] <= DATAO[1 * 8 + 7: 1 * 8];
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[0]) RAM[DADDR[11:2]][0 * 8 + 7: 0 * 8] <= DATAO[0 * 8 + 7: 0 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[0]) RAM[DADDR[11:2]][0 * 8 + 7: 0 * 8] <= DATAO[0 * 8 + 7: 0 * 8];
|
`else
|
`else
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[3]) MEM[DADDR[12:2]][3 * 8 + 7: 3 * 8] <= DATAO[3 * 8 + 7: 3 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[3]) MEM[DADDR[12:2]][3 * 8 + 7: 3 * 8] <= DATAO[3 * 8 + 7: 3 * 8];
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[2]) MEM[DADDR[12:2]][2 * 8 + 7: 2 * 8] <= DATAO[2 * 8 + 7: 2 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[2]) MEM[DADDR[12:2]][2 * 8 + 7: 2 * 8] <= DATAO[2 * 8 + 7: 2 * 8];
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[1]) MEM[DADDR[12:2]][1 * 8 + 7: 1 * 8] <= DATAO[1 * 8 + 7: 1 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[1]) MEM[DADDR[12:2]][1 * 8 + 7: 1 * 8] <= DATAO[1 * 8 + 7: 1 * 8];
|
if(WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[0]) MEM[DADDR[12:2]][0 * 8 + 7: 0 * 8] <= DATAO[0 * 8 + 7: 0 * 8];
|
if(!HLT&&WR&&DADDR[31]==0&&/*DADDR[12]==1&&*/BE[0]) MEM[DADDR[12:2]][0 * 8 + 7: 0 * 8] <= DATAO[0 * 8 + 7: 0 * 8];
|
`endif
|
`endif
|
`endif
|
`endif
|
|
|
IOMUXFF <= IOMUX[DADDR[3:2]]; // read w/ 2 wait-states
|
IOMUXFF <= IOMUX[DADDR[3:2]]; // read w/ 2 wait-states
|
end
|
end
|
|
|
//assign DATAI = DADDR[31] ? IOMUX[DADDR[3:2]] : RAMFF;
|
//assign DATAI = DADDR[31] ? IOMUX[DADDR[3:2]] : RAMFF;
|
assign DATAI = DADDR[31] ? /*IOMUX[DADDR[3:2]]*/ IOMUXFF : RAMFF;
|
assign DATAI = DADDR[31] ? /*IOMUX[DADDR[3:2]]*/ IOMUXFF : RAMFF;
|
|
|
`endif
|
`endif
|
|
|
// io for debug
|
// io for debug
|
|
|
reg [7:0] IREQ = 0;
|
reg [7:0] IREQ = 0;
|
reg [7:0] IACK = 0;
|
reg [7:0] IACK = 0;
|
|
|
reg [31:0] TIMERFF;
|
reg [31:0] TIMERFF;
|
|
|
wire [7:0] BOARD_IRQ;
|
wire [7:0] BOARD_IRQ;
|
|
|
wire [7:0] BOARD_ID = `BOARD_ID; // board id
|
wire [7:0] BOARD_ID = `BOARD_ID; // board id
|
wire [7:0] BOARD_CM = (`BOARD_CK/1000000); // board clock (MHz)
|
wire [7:0] BOARD_CM = (`BOARD_CK/1000000); // board clock (MHz)
|
wire [7:0] BOARD_CK = (`BOARD_CK/10000)%100; // board clock (kHz)
|
wire [7:0] BOARD_CK = (`BOARD_CK/10000)%100; // board clock (kHz)
|
|
|
assign IOMUX[0] = { BOARD_IRQ, BOARD_CK, BOARD_CM, BOARD_ID };
|
assign IOMUX[0] = { BOARD_IRQ, BOARD_CK, BOARD_CM, BOARD_ID };
|
//assign IOMUX[1] = from UART!
|
//assign IOMUX[1] = from UART!
|
assign IOMUX[2] = { GPIOFF, LEDFF };
|
assign IOMUX[2] = { GPIOFF, LEDFF };
|
assign IOMUX[3] = TIMERFF;
|
assign IOMUX[3] = TIMERFF;
|
|
|
reg [31:0] TIMER = 0;
|
reg [31:0] TIMER = 0;
|
|
|
reg XTIMER = 0;
|
reg XTIMER = 0;
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b1000)
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b1000)
|
begin
|
begin
|
LEDFF <= DATAO[15:0];
|
LEDFF <= DATAO[15:0];
|
end
|
end
|
|
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b1010)
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b1010)
|
begin
|
begin
|
GPIOFF <= DATAO[31:16];
|
GPIOFF <= DATAO[31:16];
|
end
|
end
|
|
|
if(RES)
|
if(RES)
|
TIMERFF <= (`BOARD_CK/1000000)-1; // timer set to 1MHz by default
|
TIMERFF <= (`BOARD_CK/1000000)-1; // timer set to 1MHz by default
|
else
|
else
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b1100)
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b1100)
|
begin
|
begin
|
TIMERFF <= DATAO[31:0];
|
TIMERFF <= DATAO[31:0];
|
end
|
end
|
|
|
if(RES)
|
if(RES)
|
IACK <= 0;
|
IACK <= 0;
|
else
|
else
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b0011)
|
if(WR&&DADDR[31]&&DADDR[3:0]==4'b0011)
|
begin
|
begin
|
//$display("clear io.irq = %x (ireq=%x, iack=%x)",DATAO[32:24],IREQ,IACK);
|
//$display("clear io.irq = %x (ireq=%x, iack=%x)",DATAO[32:24],IREQ,IACK);
|
|
|
IACK[7] <= DATAO[7+24] ? IREQ[7] : IACK[7];
|
IACK[7] <= DATAO[7+24] ? IREQ[7] : IACK[7];
|
IACK[6] <= DATAO[6+24] ? IREQ[6] : IACK[6];
|
IACK[6] <= DATAO[6+24] ? IREQ[6] : IACK[6];
|
IACK[5] <= DATAO[5+24] ? IREQ[5] : IACK[5];
|
IACK[5] <= DATAO[5+24] ? IREQ[5] : IACK[5];
|
IACK[4] <= DATAO[4+24] ? IREQ[4] : IACK[4];
|
IACK[4] <= DATAO[4+24] ? IREQ[4] : IACK[4];
|
IACK[3] <= DATAO[3+24] ? IREQ[3] : IACK[3];
|
IACK[3] <= DATAO[3+24] ? IREQ[3] : IACK[3];
|
IACK[2] <= DATAO[2+24] ? IREQ[2] : IACK[2];
|
IACK[2] <= DATAO[2+24] ? IREQ[2] : IACK[2];
|
IACK[1] <= DATAO[1+24] ? IREQ[1] : IACK[1];
|
IACK[1] <= DATAO[1+24] ? IREQ[1] : IACK[1];
|
IACK[0] <= DATAO[0+24] ? IREQ[0] : IACK[0];
|
IACK[0] <= DATAO[0+24] ? IREQ[0] : IACK[0];
|
end
|
end
|
|
|
if(RES)
|
if(RES)
|
IREQ <= 0;
|
IREQ <= 0;
|
else
|
else
|
if(TIMERFF)
|
if(TIMERFF)
|
begin
|
begin
|
TIMER <= TIMER ? TIMER-1 : TIMERFF;
|
TIMER <= TIMER ? TIMER-1 : TIMERFF;
|
|
|
if(TIMER==0 && IREQ==IACK)
|
if(TIMER==0 && IREQ==IACK)
|
begin
|
begin
|
IREQ[7] <= !IACK[7];
|
IREQ[7] <= !IACK[7];
|
|
|
//$display("timr0 set");
|
//$display("timr0 set");
|
end
|
end
|
|
|
XTIMER <= XTIMER+(TIMER==0);
|
XTIMER <= XTIMER+(TIMER==0);
|
end
|
end
|
end
|
end
|
|
|
assign BOARD_IRQ = IREQ^IACK;
|
assign BOARD_IRQ = IREQ^IACK;
|
|
|
assign HLT = !IHIT||!DHIT||!WHIT;
|
assign HLT = !IHIT||!DHIT||!WHIT;
|
|
|
// darkuart
|
// darkuart
|
|
|
wire [3:0] UDEBUG;
|
wire [3:0] UDEBUG;
|
|
|
darkuart
|
darkuart
|
// #(
|
// #(
|
// .BAUD((`BOARD_CK/115200))
|
// .BAUD((`BOARD_CK/115200))
|
// )
|
// )
|
uart0
|
uart0
|
(
|
(
|
.CLK(CLK),
|
.CLK(CLK),
|
.RES(RES),
|
.RES(RES),
|
.RD(!HLT&&RD&&DADDR[31]&&DADDR[3:2]==1),
|
.RD(!HLT&&RD&&DADDR[31]&&DADDR[3:2]==1),
|
.WR(!HLT&&WR&&DADDR[31]&&DADDR[3:2]==1),
|
.WR(!HLT&&WR&&DADDR[31]&&DADDR[3:2]==1),
|
.BE(BE),
|
.BE(BE),
|
.DATAI(DATAO),
|
.DATAI(DATAO),
|
.DATAO(IOMUX[1]),
|
.DATAO(IOMUX[1]),
|
//.IRQ(BOARD_IRQ[1]),
|
//.IRQ(BOARD_IRQ[1]),
|
.RXD(UART_RXD),
|
.RXD(UART_RXD),
|
.TXD(UART_TXD),
|
.TXD(UART_TXD),
|
|
`ifdef SIMULATION
|
|
.FINISH_REQ(FINISH_REQ),
|
|
`endif
|
.DEBUG(UDEBUG)
|
.DEBUG(UDEBUG)
|
);
|
);
|
|
|
// darkriscv
|
// darkriscv
|
|
|
wire [3:0] KDEBUG;
|
wire [3:0] KDEBUG;
|
|
|
darkriscv
|
darkriscv
|
// #(
|
// #(
|
// .RESET_PC(32'h00000000),
|
// .RESET_PC(32'h00000000),
|
// .RESET_SP(32'h00002000)
|
// .RESET_SP(32'h00002000)
|
// )
|
// )
|
core0
|
core0
|
(
|
(
|
`ifdef __3STAGE__
|
`ifdef __3STAGE__
|
.CLK(CLK),
|
.CLK(CLK),
|
`else
|
`else
|
.CLK(!CLK),
|
.CLK(!CLK),
|
`endif
|
`endif
|
.RES(RES),
|
.RES(RES),
|
.HLT(HLT),
|
.HLT(HLT),
|
`ifdef __THREADING__
|
//`ifdef __THREADING__
|
.IREQ(|(IREQ^IACK)),
|
// .IREQ(|(IREQ^IACK)),
|
`endif
|
//`endif
|
.IDATA(IDATA),
|
.IDATA(IDATA),
|
.IADDR(IADDR),
|
.IADDR(IADDR),
|
.DADDR(DADDR),
|
.DADDR(DADDR),
|
|
|
`ifdef __FLEXBUZZ__
|
`ifdef __FLEXBUZZ__
|
.DATAI(XATAI),
|
.DATAI(XATAI),
|
.DATAO(XATAO),
|
.DATAO(XATAO),
|
.DLEN(DLEN),
|
.DLEN(DLEN),
|
.RW(RW),
|
.RW(RW),
|
`else
|
`else
|
.DATAI(DATAI),
|
.DATAI(DATAI),
|
.DATAO(DATAO),
|
.DATAO(DATAO),
|
.BE(BE),
|
.BE(BE),
|
.WR(WR),
|
.WR(WR),
|
.RD(RD),
|
.RD(RD),
|
`endif
|
`endif
|
|
|
|
`ifdef SIMULATION
|
|
.FINISH_REQ(FINISH_REQ),
|
|
`endif
|
.DEBUG(KDEBUG)
|
.DEBUG(KDEBUG)
|
);
|
);
|
|
|
`ifdef __ICARUS__
|
`ifdef __ICARUS__
|
initial
|
initial
|
begin
|
begin
|
$dumpfile("darksocv.vcd");
|
$dumpfile("darksocv.vcd");
|
$dumpvars();
|
$dumpvars();
|
end
|
end
|
`endif
|
`endif
|
|
|
assign LED = LEDFF[3:0];
|
assign LED = LEDFF[3:0];
|
|
|
assign DEBUG = { GPIOFF[0], XTIMER, WR, RD }; // UDEBUG;
|
assign DEBUG = { GPIOFF[0], XTIMER, WR, RD }; // UDEBUG;
|
|
|
|
|