1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-04-21 12:27:27 +03:00

Adding lm32 demo to SAKC project

This commit is contained in:
Carlos Camargo
2010-05-25 21:49:58 -05:00
parent 26b0c73a84
commit 61d4408f2a
145 changed files with 27924 additions and 1501 deletions

View File

@@ -0,0 +1,15 @@
module JTAGB (
output JTCK,
output JRTI1,
output JRTI2,
output JTDI,
output JSHIFT,
output JUPDATE,
output JRSTN,
output JCE1,
output JCE2,
input JTDO1,
input JTDO2
) /*synthesis syn_black_box */;
endmodule

View File

@@ -0,0 +1,218 @@
/*-- ---------------------------------------------------------------------------
--
-- Name : ER1.v
--
-- Description:
--
-- This module is where the ER1 register implemented. ER1 and ER2 registers
-- can be registers implemented in Lattice FPGAs using normal FPGA's
-- programmable logic resources. Once they are implemented, they can be
-- accessed as if they are JTAG data registers through the FPGA JTAG port.
-- In order to accessing these registers, JTAG instructions ER1(0x32) or
-- ER2(0x38) needs to be written to the JTAG IR register for enabling the
-- ER1/ER2 accessing logic. The ER1 or ER2 accessing logic can only be
-- enabled one at a time. Once they are enabled, they will be disabled if
-- another JTAG instruction is written into the JTAG instruction register.
-- The registers allow dynamically accessing the FPGA internal information
-- even when the device is running. Therefore, they are very useful for some
-- of the IP cores. In order to let ER1/ER2 registers shared by multiple IP
-- cores or other designs, there is a ER1/ER2 structure patterned by Lattice.
-- The ER1/ER2 structure allows only one ER1 register but more than one ER2
-- registers in an FPGA device. Please refer to the related document for
-- this patterned ER1/ER2 structure.
--
-- $Log: $
--
-- $Header: $
--
-- Copyright (C) 2004 Lattice Semiconductor Corp. All rights reserved.
--
-- ---------------------------------------------------------------------------*/
module ER1 (input JTCK,
input JTDI,
output JTDO1,
output reg JTDO2,
input JSHIFT,
input JUPDATE,
input JRSTN,
input JCE1,
input [14:0] ER2_TDO,
output reg [14:0] IP_ENABLE,
input ISPTRACY_ER2_TDO,
output ISPTRACY_ENABLE,
output CONTROL_DATAN)/* synthesis syn_hier = hard */;
wire controlDataNBit;
wire ispTracyEnableBit;
wire [3:0] encodedIpEnableBits;
wire [9:0] er1TdiBit;
wire captureDrER1;
assign JTDO1 = er1TdiBit[0];
TYPEB BIT0 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[1]),
.TDO(er1TdiBit[0]),
.DATA_IN(1'b0),
.CAPTURE_DR(captureDrER1));
TYPEB BIT1 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[2]),
.TDO(er1TdiBit[1]),
.DATA_IN(1'b0),
.CAPTURE_DR(captureDrER1));
TYPEB BIT2 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[3]),
.TDO(er1TdiBit[2]),
.DATA_IN(1'b1),
.CAPTURE_DR(captureDrER1));
TYPEA BIT3 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[4]),
.TDO(er1TdiBit[3]),
.DATA_OUT(controlDataNBit),
.DATA_IN(controlDataNBit),
.CAPTURE_DR(captureDrER1),
.UPDATE_DR(JUPDATE));
assign CONTROL_DATAN = controlDataNBit;
TYPEA BIT4 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[5]),
.TDO(er1TdiBit[4]),
.DATA_OUT(ispTracyEnableBit),
.DATA_IN(ispTracyEnableBit),
.CAPTURE_DR(captureDrER1),
.UPDATE_DR(JUPDATE)
);
assign ISPTRACY_ENABLE = ispTracyEnableBit;
TYPEA BIT5 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[6]),
.TDO(er1TdiBit[5]),
.DATA_OUT(encodedIpEnableBits[0]),
.DATA_IN(encodedIpEnableBits[0]),
.CAPTURE_DR(captureDrER1),
.UPDATE_DR(JUPDATE));
TYPEA BIT6 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[7]),
.TDO(er1TdiBit[6]),
.DATA_OUT(encodedIpEnableBits[1]),
.DATA_IN(encodedIpEnableBits[1]),
.CAPTURE_DR(captureDrER1),
.UPDATE_DR(JUPDATE));
TYPEA BIT7 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[8]),
.TDO(er1TdiBit[7]),
.DATA_OUT(encodedIpEnableBits[2]),
.DATA_IN(encodedIpEnableBits[2]),
.CAPTURE_DR(captureDrER1),
.UPDATE_DR(JUPDATE));
TYPEA BIT8 (.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(JCE1),
.TDI(er1TdiBit[9]),
.TDO(er1TdiBit[8]),
.DATA_OUT(encodedIpEnableBits[3]),
.DATA_IN(encodedIpEnableBits[3]),
.CAPTURE_DR(captureDrER1),
.UPDATE_DR(JUPDATE)
);
assign er1TdiBit[9] = JTDI;
assign captureDrER1 = !JSHIFT & JCE1;
always @ (encodedIpEnableBits,ISPTRACY_ER2_TDO, ER2_TDO)
begin
case (encodedIpEnableBits)
4'h0: begin
IP_ENABLE <= 15'b000000000000000;
JTDO2 <= ISPTRACY_ER2_TDO;
end
4'h1: begin
IP_ENABLE <= 15'b000000000000001;
JTDO2 <= ER2_TDO[0];
end
4'h2: begin
IP_ENABLE <= 15'b000000000000010;
JTDO2 <= ER2_TDO[1];
end
4'h3: begin
IP_ENABLE <= 15'b000000000000100;
JTDO2 <= ER2_TDO[2];
end
4'h4: begin
IP_ENABLE <= 15'b000000000001000;
JTDO2 <= ER2_TDO[3];
end
4'h5: begin
IP_ENABLE <= 15'b000000000010000;
JTDO2 <= ER2_TDO[4];
end
4'h6: begin
IP_ENABLE <= 15'b000000000100000;
JTDO2 <= ER2_TDO[5];
end
4'h7: begin
IP_ENABLE <= 15'b000000001000000;
JTDO2 <= ER2_TDO[6];
end
4'h8: begin
IP_ENABLE <= 15'b000000010000000;
JTDO2 <= ER2_TDO[7];
end
4'h9: begin
IP_ENABLE <= 15'b000000100000000;
JTDO2 <= ER2_TDO[8];
end
4'hA: begin
IP_ENABLE <= 15'b000001000000000;
JTDO2 <= ER2_TDO[9];
end
4'hB: begin
IP_ENABLE <= 15'b000010000000000;
JTDO2 <= ER2_TDO[10];
end
4'hC: begin
IP_ENABLE <= 15'b000100000000000;
JTDO2 <= ER2_TDO[11];
end
4'hD: begin
IP_ENABLE <= 15'b001000000000000;
JTDO2 <= ER2_TDO[12];
end
4'hE: begin
IP_ENABLE <= 15'b010000000000000;
JTDO2 <= ER2_TDO[13];
end
4'hF: begin
IP_ENABLE <= 15'b100000000000000;
JTDO2 <= ER2_TDO[14];
end
endcase
end
endmodule

View File

@@ -0,0 +1,213 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : jtag_cores.v
// Title : Instantiates all IP cores on JTAG chain.
// Dependencies : system_conf.v
// Version : 6.0.13
// =============================================================================
`include "system_conf.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module jtag_cores (
// ----- Inputs -------
`ifdef INCLUDE_LM32
reg_d,
reg_addr_d,
`endif
`ifdef INCLUDE_SPI
spi_q,
`endif
// ----- Outputs -------
`ifdef INCLUDE_LM32
reg_update,
reg_q,
reg_addr_q,
`endif
`ifdef INCLUDE_SPI
spi_c,
spi_d,
spi_sn,
`endif
jtck,
jrstn
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
`ifdef INCLUDE_LM32
input [7:0] reg_d;
input [2:0] reg_addr_d;
`endif
`ifdef INCLUDE_SPI
input spi_q;
`endif
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
`ifdef INCLUDE_LM32
output reg_update;
wire reg_update;
output [7:0] reg_q;
wire [7:0] reg_q;
output [2:0] reg_addr_q;
wire [2:0] reg_addr_q;
`endif
`ifdef INCLUDE_SPI
output spi_c;
wire spi_c;
output spi_d;
wire spi_d;
output spi_sn;
wire spi_sn;
`endif
output jtck;
wire jtck; /* synthesis ER1_MARK="jtck" */ /* synthesis syn_keep=1 */
output jrstn;
wire jrstn; /* synthesis ER1_MARK="jrstn" */ /* synthesis syn_keep=1 */
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire rtiER1;
wire rtiER2;
wire tdi;/* synthesis ER1_MARK="jtdi" */ /* synthesis syn_keep=1 */
wire tdoEr1;/* synthesis ER1_MARK="jtdo1" */ /* synthesis syn_keep=1 */
wire tdoEr2;
wire jtdo2_mux;/* synthesis ER1_MARK="jtdo2" */ /* synthesis syn_keep=1 */
wire spi_tdo2;
wire shiftDr;/* synthesis ER1_MARK="jshift" */ /* synthesis syn_keep=1 */
wire updateDr;/* synthesis ER1_MARK="jupdate" */ /* synthesis syn_keep=1 */
wire enableEr1;/* synthesis ER1_MARK="jce1" */ /* synthesis syn_keep=1 */
wire enableEr2;/* synthesis ER1_MARK="jce2" */ /* synthesis syn_keep=1 */
wire [14:0] ipEnable;/* synthesis ER1_MARK="ip_enable" */ /* synthesis syn_keep=1 */
wire controlDataN;/* synthesis ER1_MARK="control_datan" */ /* synthesis syn_keep=1 */
wire lm32_isptracy_enable;/* synthesis ER1_MARK="isptracy_enable" */ /* synthesis syn_keep=1 */
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
parameter lat_family = `LATTICE_FAMILY;
generate
if (lat_family == "EC" || lat_family == "ECP" || lat_family == "XP") begin
JTAGB jtagb (.JTCK (jtck),
.JRTI1 (rtiER1),
.JRTI2 (rtiER2),
.JTDI (tdi),
.JSHIFT (shiftDr),
.JUPDATE (updateDr),
.JRSTN (jrstn),
.JCE1 (enableEr1),
.JCE2 (enableEr2),
.JTDO1 (tdoEr1),
.JTDO2 (jtdo2_mux)) /* synthesis ER1="ENABLED" */ /* synthesis ER2="ENABLED" */ /* synthesis JTAG_FLASH_PRGRM="DISABLED" */;
end else if (lat_family == "ECP2" || lat_family == "ECP2M") begin
JTAGC jtagc (.JTCK (jtck),
.JRTI1 (rtiER1),
.JRTI2 (rtiER2),
.JTDI (tdi),
.JSHIFT (shiftDr),
.JUPDATE (updateDr),
.JRSTN (jrstn),
.IJTAGEN (1'b1),
.JCE1 (enableEr1),
.JCE2 (enableEr2),
.JTDO1 (tdoEr1),
.JTDO2 (jtdo2_mux)) /* synthesis ER1="ENABLED" */ /* synthesis ER2="ENABLED" */ /* synthesis JTAG_FLASH_PRGRM="DISABLED" */;
end else if (lat_family == "SC" || lat_family == "SCM") begin // if (lat_family == "ECP2" || lat_family == "ECP2M")
JTAGA jtaga(.JTCK (jtck),
.JRTI1 (rtiER1),
.JRTI2 (rtiER2),
.JTDI (tdi),
.JSHIFT (shiftDr),
.JUPDATE (updateDr),
.JRSTN (jrstn),
.JCE1 (enableEr1),
.JCE2 (enableEr2),
.JTDO1 (tdoEr1),
.JTDO2 (jtdo2_mux)) /* synthesis ER1="ENABLED" */ /* synthesis ER2="ENABLED" */ /* synthesis JTAG_FLASH_PRGRM="DISABLED" */;
end
endgenerate
ER1 er1 (
.JTCK (jtck),
.JTDI (tdi),
.JTDO1 (tdoEr1),
.JTDO2 (jtdo2_mux),
.JSHIFT (shiftDr),
.JUPDATE (updateDr),
.JRSTN (jrstn),
.JCE1 (enableEr1),
.ER2_TDO ({13'b0,tdoEr2,spi_tdo2}),
.IP_ENABLE (ipEnable),
.ISPTRACY_ENABLE(lm32_isptracy_enable),
.ISPTRACY_ER2_TDO(lm32_isptracy_enable),
.CONTROL_DATAN (controlDataN));
`ifdef INCLUDE_LM32
jtag_lm32 jtag_lm32 (
.JTCK (jtck),
.JTDI (tdi),
.JTDO2 (tdoEr2),
.JSHIFT (shiftDr),
.JUPDATE (updateDr),
.JRSTN (jrstn),
.JCE2 (enableEr2),
.JTAGREG_ENABLE (ipEnable[1]),
.CONTROL_DATAN (controlDataN),
.REG_UPDATE (reg_update),
.REG_D (reg_d),
.REG_ADDR_D (reg_addr_d),
.REG_Q (reg_q),
.REG_ADDR_Q (reg_addr_q)
);
`endif
`ifdef INCLUDE_SPI
SPIPROG spiprog_inst (
.JTCK (tck),
.JTDI (tdi),
.JTDO2 (spi_tdo2),
.JSHIFT (shiftDr),
.JUPDATE (updateDr),
.JRSTN (resetN),
.JCE2 (enableEr2),
.SPIPROG_ENABLE (ipEnable[0]),
.CONTROL_DATAN (controlDataN),
.SPI_C (spi_c),
.SPI_D (spi_d),
.SPI_SN (spi_sn),
.SPI_Q (spi_q)
);
`endif
endmodule

View File

@@ -0,0 +1,195 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : jtag_lm32.v
// Title : JTAG data register for LM32 CPU debug interface
// Version : 6.0.13
// =============================================================================
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module jtag_lm32 (
input JTCK,
input JTDI,
output JTDO2,
input JSHIFT,
input JUPDATE,
input JRSTN,
input JCE2,
input JTAGREG_ENABLE,
input CONTROL_DATAN,
output REG_UPDATE,
input [7:0] REG_D,
input [2:0] REG_ADDR_D,
output [7:0] REG_Q,
output [2:0] REG_ADDR_Q
);
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire [9:0] tdibus;
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
TYPEA DATA_BIT0 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(JTDI),
.TDO(tdibus[0]),
.DATA_OUT(REG_Q[0]),
.DATA_IN(REG_D[0]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT1 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[0]),
.TDO(tdibus[1]),
.DATA_OUT(REG_Q[1]),
.DATA_IN(REG_D[1]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT2 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[1]),
.TDO(tdibus[2]),
.DATA_OUT(REG_Q[2]),
.DATA_IN(REG_D[2]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT3 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[2]),
.TDO(tdibus[3]),
.DATA_OUT(REG_Q[3]),
.DATA_IN(REG_D[3]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT4 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[3]),
.TDO(tdibus[4]),
.DATA_OUT(REG_Q[4]),
.DATA_IN(REG_D[4]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT5 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[4]),
.TDO(tdibus[5]),
.DATA_OUT(REG_Q[5]),
.DATA_IN(REG_D[5]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT6 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[5]),
.TDO(tdibus[6]),
.DATA_OUT(REG_Q[6]),
.DATA_IN(REG_D[6]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA DATA_BIT7 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[6]),
.TDO(tdibus[7]),
.DATA_OUT(REG_Q[7]),
.DATA_IN(REG_D[7]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA ADDR_BIT0 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[7]),
.TDO(tdibus[8]),
.DATA_OUT(REG_ADDR_Q[0]),
.DATA_IN(REG_ADDR_D[0]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA ADDR_BIT1 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[8]),
.TDO(tdibus[9]),
.DATA_OUT(REG_ADDR_Q[1]),
.DATA_IN(REG_ADDR_D[1]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
TYPEA ADDR_BIT2 (
.CLK(JTCK),
.RESET_N(JRSTN),
.CLKEN(clk_enable),
.TDI(tdibus[9]),
.TDO(JTDO2),
.DATA_OUT(REG_ADDR_Q[2]),
.DATA_IN(REG_ADDR_D[2]),
.CAPTURE_DR(captureDr),
.UPDATE_DR(JUPDATE)
);
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
assign clk_enable = JTAGREG_ENABLE & JCE2;
assign captureDr = !JSHIFT & JCE2;
// JCE2 is only active during shift
assign REG_UPDATE = JTAGREG_ENABLE & JUPDATE;
endmodule

View File

@@ -0,0 +1,110 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// ============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_adder.v
// Title : Integer adder / subtractor with comparison flag generation
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_adder (
// ----- Inputs -------
adder_op_x,
adder_op_x_n,
operand_0_x,
operand_1_x,
// ----- Outputs -------
adder_result_x,
adder_carry_n_x,
adder_overflow_x
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input adder_op_x; // Operating to perform, 0 for addition, 1 for subtraction
input adder_op_x_n; // Inverted version of adder_op_x
input [`LM32_WORD_RNG] operand_0_x; // Operand to add, or subtract from
input [`LM32_WORD_RNG] operand_1_x; // Opearnd to add, or subtract by
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] adder_result_x; // Result of addition or subtraction
wire [`LM32_WORD_RNG] adder_result_x;
output adder_carry_n_x; // Inverted carry
wire adder_carry_n_x;
output adder_overflow_x; // Indicates if overflow occured, only valid for subtractions
reg adder_overflow_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire a_sign; // Sign (i.e. positive or negative) of operand 0
wire b_sign; // Sign of operand 1
wire result_sign; // Sign of result
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
lm32_addsub addsub (
// ----- Inputs -----
.DataA (operand_0_x),
.DataB (operand_1_x),
.Cin (adder_op_x),
.Add_Sub (adder_op_x_n),
// ----- Ouputs -----
.Result (adder_result_x),
.Cout (adder_carry_n_x)
);
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Extract signs of operands and result
assign a_sign = operand_0_x[`LM32_WORD_WIDTH-1];
assign b_sign = operand_1_x[`LM32_WORD_WIDTH-1];
assign result_sign = adder_result_x[`LM32_WORD_WIDTH-1];
// Determine whether an overflow occured when performing a subtraction
always @*
begin
// +ve - -ve = -ve -> overflow
// -ve - +ve = +ve -> overflow
if ( (!a_sign & b_sign & result_sign)
|| (a_sign & !b_sign & !result_sign)
)
adder_overflow_x = `TRUE;
else
adder_overflow_x = `FALSE;
end
endmodule

View File

@@ -0,0 +1,69 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_addsub.v
// Title : PMI adder/subtractor.
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_addsub (
// ----- Inputs -------
DataA,
DataB,
Cin,
Add_Sub,
// ----- Outputs -------
Result,
Cout
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input [31:0] DataA;
input [31:0] DataB;
input Cin;
input Add_Sub;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [31:0] Result;
wire [31:0] Result;
output Cout;
wire Cout;
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
wire [32:0] tmp_addResult = DataA + DataB + Cin;
wire [32:0] tmp_subResult = DataA - DataB - !Cin;
assign Result = (Add_Sub == 1) ? tmp_addResult[31:0] : tmp_subResult[31:0];
assign Cout = (Add_Sub == 1) ? tmp_addResult[32] : !tmp_subResult[32];
endmodule

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,494 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_dcache.v
// Title : Data cache
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
`ifdef CFG_DCACHE_ENABLED
`define LM32_DC_ADDR_OFFSET_RNG addr_offset_msb:addr_offset_lsb
`define LM32_DC_ADDR_SET_RNG addr_set_msb:addr_set_lsb
`define LM32_DC_ADDR_TAG_RNG addr_tag_msb:addr_tag_lsb
`define LM32_DC_ADDR_IDX_RNG addr_set_msb:addr_offset_lsb
`define LM32_DC_TMEM_ADDR_WIDTH addr_set_width
`define LM32_DC_TMEM_ADDR_RNG (`LM32_DC_TMEM_ADDR_WIDTH-1):0
`define LM32_DC_DMEM_ADDR_WIDTH (addr_offset_width+addr_set_width)
`define LM32_DC_DMEM_ADDR_RNG (`LM32_DC_DMEM_ADDR_WIDTH-1):0
`define LM32_DC_TAGS_WIDTH (addr_tag_width+1)
`define LM32_DC_TAGS_RNG (`LM32_DC_TAGS_WIDTH-1):0
`define LM32_DC_TAGS_TAG_RNG (`LM32_DC_TAGS_WIDTH-1):1
`define LM32_DC_TAGS_VALID_RNG 0
`define LM32_DC_STATE_RNG 2:0
`define LM32_DC_STATE_FLUSH 3'b001
`define LM32_DC_STATE_CHECK 3'b010
`define LM32_DC_STATE_REFILL 3'b100
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_dcache (
// ----- Inputs -----
clk_i,
rst_i,
stall_a,
stall_x,
stall_m,
address_x,
address_m,
load_q_m,
store_q_m,
store_data,
store_byte_select,
refill_ready,
refill_data,
dflush,
// ----- Outputs -----
stall_request,
restart_request,
refill_request,
refill_address,
refilling,
load_data
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter associativity = 1; // Associativity of the cache (Number of ways)
parameter sets = 512; // Number of sets
parameter bytes_per_line = 16; // Number of bytes per cache line
parameter base_address = 0; // Base address of cachable memory
parameter limit = 0; // Limit (highest address) of cachable memory
//localparam addr_offset_width = clogb2(bytes_per_line)-1-2;
localparam addr_offset_width = 2;
//localparam addr_set_width = clogb2(sets)-1;
localparam addr_set_width = 9;
localparam addr_offset_lsb = 2;
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
localparam addr_set_lsb = (addr_offset_msb+1);
localparam addr_set_msb = (addr_set_lsb+addr_set_width-1);
localparam addr_tag_lsb = (addr_set_msb+1);
localparam addr_tag_msb = 31;
localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_a; // Stall A stage
input stall_x; // Stall X stage
input stall_m; // Stall M stage
input [`LM32_WORD_RNG] address_x; // X stage load/store address
input [`LM32_WORD_RNG] address_m; // M stage load/store address
input load_q_m; // Load instruction in M stage
input store_q_m; // Store instruction in M stage
input [`LM32_WORD_RNG] store_data; // Data to store
input [`LM32_BYTE_SELECT_RNG] store_byte_select; // Which bytes in store data should be modified
input refill_ready; // Indicates next word of refill data is ready
input [`LM32_WORD_RNG] refill_data; // Refill data
input dflush; // Indicates cache should be flushed
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output stall_request; // Request pipeline be stalled because cache is busy
wire stall_request;
output restart_request; // Request to restart instruction that caused the cache miss
reg restart_request;
output refill_request; // Request a refill
reg refill_request;
output [`LM32_WORD_RNG] refill_address; // Address to refill from
reg [`LM32_WORD_RNG] refill_address;
output refilling; // Indicates if the cache is currently refilling
reg refilling;
output [`LM32_WORD_RNG] load_data; // Data read from cache
wire [`LM32_WORD_RNG] load_data;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire read_port_enable; // Cache memory read port clock enable
wire write_port_enable; // Cache memory write port clock enable
wire [0:associativity-1] way_tmem_we; // Tag memory write enable
wire [0:associativity-1] way_dmem_we; // Data memory write enable
wire [`LM32_WORD_RNG] way_data[0:associativity-1]; // Data read from data memory
wire [`LM32_DC_TAGS_TAG_RNG] way_tag[0:associativity-1];// Tag read from tag memory
wire [0:associativity-1] way_valid; // Indicates which ways are valid
wire [0:associativity-1] way_match; // Indicates which ways matched
wire miss; // Indicates no ways matched
wire [`LM32_DC_TMEM_ADDR_RNG] tmem_read_address; // Tag memory read address
wire [`LM32_DC_TMEM_ADDR_RNG] tmem_write_address; // Tag memory write address
wire [`LM32_DC_DMEM_ADDR_RNG] dmem_read_address; // Data memory read address
wire [`LM32_DC_DMEM_ADDR_RNG] dmem_write_address; // Data memory write address
wire [`LM32_DC_TAGS_RNG] tmem_write_data; // Tag memory write data
reg [`LM32_WORD_RNG] dmem_write_data; // Data memory write data
reg [`LM32_DC_STATE_RNG] state; // Current state of FSM
wire flushing; // Indicates if cache is currently flushing
wire check; // Indicates if cache is currently checking for hits/misses
wire refill; // Indicates if cache is currently refilling
wire valid_store; // Indicates if there is a valid store instruction
reg [associativity-1:0] refill_way_select; // Which way should be refilled
reg [`LM32_DC_ADDR_OFFSET_RNG] refill_offset; // Which word in cache line should be refilled
wire last_refill; // Indicates when on last cycle of cache refill
reg [`LM32_DC_TMEM_ADDR_RNG] flush_set; // Which set is currently being flushed
genvar i, j;
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
generate
for (i = 0; i < associativity; i = i + 1)
begin : memories
// Way data
if (`LM32_DC_DMEM_ADDR_WIDTH < 7)
begin : data_memories
lm32_ram #(
// ----- Parameters -------
.data_width (32),
.address_width (`LM32_DC_DMEM_ADDR_WIDTH)
) way_0_data_ram (
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (dmem_read_address),
.enable_read (read_port_enable),
.write_address (dmem_write_address),
.enable_write (write_port_enable),
.write_enable (way_dmem_we[i]),
.write_data (dmem_write_data),
// ----- Outputs -------
.read_data (way_data[i])
);
end
else
begin
for (j = 0; j < 4; j = j + 1)
begin : byte_memories
lm32_ram #(
// ----- Parameters -------
.data_width (8),
.address_width (`LM32_DC_DMEM_ADDR_WIDTH)
) way_0_data_ram (
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (dmem_read_address),
.enable_read (read_port_enable),
.write_address (dmem_write_address),
.enable_write (write_port_enable),
.write_enable (way_dmem_we[i] & (store_byte_select[j] | refill)),
.write_data (dmem_write_data[(j+1)*8-1:j*8]),
// ----- Outputs -------
.read_data (way_data[i][(j+1)*8-1:j*8])
);
end
end
// Way tags
lm32_ram #(
// ----- Parameters -------
.data_width (`LM32_DC_TAGS_WIDTH),
.address_width (`LM32_DC_TMEM_ADDR_WIDTH)
) way_0_tag_ram (
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (tmem_read_address),
.enable_read (read_port_enable),
.write_address (tmem_write_address),
.enable_write (`TRUE),
.write_enable (way_tmem_we[i]),
.write_data (tmem_write_data),
// ----- Outputs -------
.read_data ({way_tag[i], way_valid[i]})
);
end
endgenerate
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Compute which ways in the cache match the address being read
generate
for (i = 0; i < associativity; i = i + 1)
begin : match
assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});
end
endgenerate
// Select data from way that matched the address being read
generate
if (associativity == 1)
begin : data_1
assign load_data = way_data[0];
end
else if (associativity == 2)
begin : data_2
assign load_data = way_match[0] ? way_data[0] : way_data[1];
end
endgenerate
generate
if (`LM32_DC_DMEM_ADDR_WIDTH < 7)
begin
// Select data to write to data memories
always @(*)
begin
if (refill == `TRUE)
dmem_write_data = refill_data;
else
begin
dmem_write_data[`LM32_BYTE_0_RNG] = store_byte_select[0] ? store_data[`LM32_BYTE_0_RNG] : load_data[`LM32_BYTE_0_RNG];
dmem_write_data[`LM32_BYTE_1_RNG] = store_byte_select[1] ? store_data[`LM32_BYTE_1_RNG] : load_data[`LM32_BYTE_1_RNG];
dmem_write_data[`LM32_BYTE_2_RNG] = store_byte_select[2] ? store_data[`LM32_BYTE_2_RNG] : load_data[`LM32_BYTE_2_RNG];
dmem_write_data[`LM32_BYTE_3_RNG] = store_byte_select[3] ? store_data[`LM32_BYTE_3_RNG] : load_data[`LM32_BYTE_3_RNG];
end
end
end
else
begin
// Select data to write to data memories - FIXME: Should use different write ports on dual port RAMs, but they don't work
always @(*)
begin
if (refill == `TRUE)
dmem_write_data = refill_data;
else
dmem_write_data = store_data;
end
end
endgenerate
// Compute address to use to index into the data memories
generate
if (bytes_per_line > 4)
assign dmem_write_address = (refill == `TRUE)
? {refill_address[`LM32_DC_ADDR_SET_RNG], refill_offset}
: address_m[`LM32_DC_ADDR_IDX_RNG];
else
assign dmem_write_address = (refill == `TRUE)
? refill_address[`LM32_DC_ADDR_SET_RNG]
: address_m[`LM32_DC_ADDR_IDX_RNG];
endgenerate
assign dmem_read_address = address_x[`LM32_DC_ADDR_IDX_RNG];
// Compute address to use to index into the tag memories
assign tmem_write_address = (flushing == `TRUE)
? flush_set
: refill_address[`LM32_DC_ADDR_SET_RNG];
assign tmem_read_address = address_x[`LM32_DC_ADDR_SET_RNG];
// Compute signal to indicate when we are on the last refill accesses
generate
if (bytes_per_line > 4)
assign last_refill = refill_offset == {addr_offset_width{1'b1}};
else
assign last_refill = `TRUE;
endgenerate
// Compute data and tag memory access enable
assign read_port_enable = (stall_x == `FALSE);
assign write_port_enable = (refill_ready == `TRUE) || !stall_m;
// Determine when we have a valid store
assign valid_store = (store_q_m == `TRUE) && (check == `TRUE);
// Compute data and tag memory write enables
generate
if (associativity == 1)
begin : we_1
assign way_dmem_we[0] = (refill_ready == `TRUE) || ((valid_store == `TRUE) && (way_match[0] == `TRUE));
assign way_tmem_we[0] = (refill_ready == `TRUE) || (flushing == `TRUE);
end
else
begin : we_2
assign way_dmem_we[0] = ((refill_ready == `TRUE) && (refill_way_select[0] == `TRUE)) || ((valid_store == `TRUE) && (way_match[0] == `TRUE));
assign way_dmem_we[1] = ((refill_ready == `TRUE) && (refill_way_select[1] == `TRUE)) || ((valid_store == `TRUE) && (way_match[1] == `TRUE));
assign way_tmem_we[0] = ((refill_ready == `TRUE) && (refill_way_select[0] == `TRUE)) || (flushing == `TRUE);
assign way_tmem_we[1] = ((refill_ready == `TRUE) && (refill_way_select[1] == `TRUE)) || (flushing == `TRUE);
end
endgenerate
// On the last refill cycle set the valid bit, for all other writes it should be cleared
assign tmem_write_data[`LM32_DC_TAGS_VALID_RNG] = ((last_refill == `TRUE) || (valid_store == `TRUE)) && (flushing == `FALSE);
assign tmem_write_data[`LM32_DC_TAGS_TAG_RNG] = refill_address[`LM32_DC_ADDR_TAG_RNG];
// Signals that indicate which state we are in
assign flushing = state[0];
assign check = state[1];
assign refill = state[2];
assign miss = (~(|way_match)) && (load_q_m == `TRUE) && (stall_m == `FALSE);
assign stall_request = (check == `FALSE);
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
// Record way selected for replacement on a cache miss
generate
if (associativity >= 2)
begin : way_select
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
refill_way_select <= {{associativity-1{1'b0}}, 1'b1};
else
begin
if (refill_request == `TRUE)
refill_way_select <= {refill_way_select[0], refill_way_select[1]};
end
end
end
endgenerate
// Record whether we are currently refilling
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
refilling <= `FALSE;
else
refilling <= refill;
end
// Instruction cache control FSM
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
state <= `LM32_DC_STATE_FLUSH;
flush_set <= {`LM32_DC_TMEM_ADDR_WIDTH{1'b1}};
refill_request <= `FALSE;
refill_address <= {`LM32_WORD_WIDTH{1'bx}};
restart_request <= `FALSE;
end
else
begin
case (state)
// Flush the cache
`LM32_DC_STATE_FLUSH:
begin
if (flush_set == {`LM32_DC_TMEM_ADDR_WIDTH{1'b0}})
state <= `LM32_DC_STATE_CHECK;
flush_set <= flush_set - 1'b1;
end
// Check for cache misses
`LM32_DC_STATE_CHECK:
begin
if (stall_a == `FALSE)
restart_request <= `FALSE;
if (miss == `TRUE)
begin
refill_request <= `TRUE;
refill_address <= address_m;
state <= `LM32_DC_STATE_REFILL;
end
else if (dflush == `TRUE)
state <= `LM32_DC_STATE_FLUSH;
end
// Refill a cache line
`LM32_DC_STATE_REFILL:
begin
refill_request <= `FALSE;
if (refill_ready == `TRUE)
begin
if (last_refill == `TRUE)
begin
restart_request <= `TRUE;
state <= `LM32_DC_STATE_CHECK;
end
end
end
endcase
end
end
generate
if (bytes_per_line > 4)
begin
// Refill offset
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
refill_offset <= {addr_offset_width{1'b0}};
else
begin
case (state)
// Check for cache misses
`LM32_DC_STATE_CHECK:
begin
if (miss == `TRUE)
refill_offset <= {addr_offset_width{1'b0}};
end
// Refill a cache line
`LM32_DC_STATE_REFILL:
begin
if (refill_ready == `TRUE)
refill_offset <= refill_offset + 1'b1;
end
endcase
end
end
end
endgenerate
endmodule
`endif

View File

@@ -0,0 +1,340 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_debug.v
// Title : Hardware debug registers and associated logic.
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
`ifdef CFG_DEBUG_ENABLED
// States for single-step FSM
`define LM32_DEBUG_SS_STATE_RNG 2:0
`define LM32_DEBUG_SS_STATE_IDLE 3'b000
`define LM32_DEBUG_SS_STATE_WAIT_FOR_RET 3'b001
`define LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN 3'b010
`define LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT 3'b011
`define LM32_DEBUG_SS_STATE_RESTART 3'b100
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_debug (
// ----- Inputs -------
clk_i,
rst_i,
pc_x,
load_x,
store_x,
load_store_address_x,
csr_write_enable_x,
csr_write_data,
csr_x,
`ifdef CFG_HW_DEBUG_ENABLED
jtag_csr_write_enable,
jtag_csr_write_data,
jtag_csr,
`endif
`ifdef LM32_SINGLE_STEP_ENABLED
eret_q_x,
bret_q_x,
stall_x,
exception_x,
q_x,
`ifdef CFG_DCACHE_ENABLED
dcache_refill_request,
`endif
`endif
// ----- Outputs -------
`ifdef LM32_SINGLE_STEP_ENABLED
dc_ss,
`endif
dc_re,
bp_match,
wp_match
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter breakpoints = 0; // Number of breakpoint CSRs
parameter watchpoints = 0; // Number of watchpoint CSRs
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input [`LM32_PC_RNG] pc_x; // X stage PC
input load_x; // Load instruction in X stage
input store_x; // Store instruction in X stage
input [`LM32_WORD_RNG] load_store_address_x; // Load or store effective address
input csr_write_enable_x; // wcsr instruction in X stage
input [`LM32_WORD_RNG] csr_write_data; // Data to write to CSR
input [`LM32_CSR_RNG] csr_x; // Which CSR to write
`ifdef CFG_HW_DEBUG_ENABLED
input jtag_csr_write_enable; // JTAG interface CSR write enable
input [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to CSR
input [`LM32_CSR_RNG] jtag_csr; // Which CSR to write
`endif
`ifdef LM32_SINGLE_STEP_ENABLED
input eret_q_x; // eret instruction in X stage
input bret_q_x; // bret instruction in X stage
input stall_x; // Instruction in X stage is stalled
input exception_x; // An exception has occured in X stage
input q_x; // Indicates the instruction in the X stage is qualified
`ifdef CFG_DCACHE_ENABLED
input dcache_refill_request; // Indicates data cache wants to be refilled
`endif
`endif
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
`ifdef LM32_SINGLE_STEP_ENABLED
output dc_ss; // Single-step enable
reg dc_ss;
`endif
output dc_re; // Remap exceptions
reg dc_re;
output bp_match; // Indicates a breakpoint has matched
wire bp_match;
output wp_match; // Indicates a watchpoint has matched
wire wp_match;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
genvar i; // Loop index for generate statements
// Debug CSRs
reg [`LM32_PC_RNG] bp_a[0:breakpoints-1]; // Instruction breakpoint address
reg bp_e[0:breakpoints-1]; // Instruction breakpoint enable
wire [0:breakpoints-1]bp_match_n; // Indicates if a h/w instruction breakpoint matched
reg [`LM32_WPC_C_RNG] wpc_c[0:watchpoints-1]; // Watchpoint enable
reg [`LM32_WORD_RNG] wp[0:watchpoints-1]; // Watchpoint address
wire [0:watchpoints-1]wp_match_n; // Indicates if a h/w data watchpoint matched
wire debug_csr_write_enable; // Debug CSR write enable (from either a wcsr instruction of external debugger)
wire [`LM32_WORD_RNG] debug_csr_write_data; // Data to write to debug CSR
wire [`LM32_CSR_RNG] debug_csr; // Debug CSR to write to
`ifdef LM32_SINGLE_STEP_ENABLED
// FIXME: Declaring this as a reg causes ModelSim 6.1.15b to crash, so use integer for now
//reg [`LM32_DEBUG_SS_STATE_RNG] state; // State of single-step FSM
integer state; // State of single-step FSM
`endif
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Check for breakpoints
generate
for (i = 0; i < breakpoints; i = i + 1)
begin : bp_comb
assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == `TRUE));
end
endgenerate
generate
`ifdef LM32_SINGLE_STEP_ENABLED
if (breakpoints > 0)
assign bp_match = (|bp_match_n) || (state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT);
else
assign bp_match = state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
`else
if (breakpoints > 0)
assign bp_match = |bp_match_n;
else
assign bp_match = `FALSE;
`endif
endgenerate
// Check for watchpoints
generate
for (i = 0; i < watchpoints; i = i + 1)
begin : wp_comb
assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1]));
end
endgenerate
generate
if (watchpoints > 0)
assign wp_match = |wp_match_n;
else
assign wp_match = `FALSE;
endgenerate
`ifdef CFG_HW_DEBUG_ENABLED
// Multiplex between wcsr instruction writes and debugger writes to the debug CSRs
assign debug_csr_write_enable = (csr_write_enable_x == `TRUE) || (jtag_csr_write_enable == `TRUE);
assign debug_csr_write_data = jtag_csr_write_enable == `TRUE ? jtag_csr_write_data : csr_write_data;
assign debug_csr = jtag_csr_write_enable == `TRUE ? jtag_csr : csr_x;
`else
assign debug_csr_write_enable = csr_write_enable_x;
assign debug_csr_write_data = csr_write_data;
assign debug_csr = csr_x;
`endif
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// Breakpoint address and enable CSRs
generate
for (i = 0; i < breakpoints; i = i + 1)
begin : bp_seq
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
bp_a[i] <= {`LM32_PC_WIDTH{1'bx}};
bp_e[i] <= `FALSE;
end
else
begin
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_BP0 + i))
begin
bp_a[i] <= debug_csr_write_data[`LM32_PC_RNG];
bp_e[i] <= debug_csr_write_data[0];
end
end
end
end
endgenerate
// Watchpoint address and control flags CSRs
generate
for (i = 0; i < watchpoints; i = i + 1)
begin : wp_seq
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
wp[i] <= {`LM32_WORD_WIDTH{1'bx}};
wpc_c[i] <= `LM32_WPC_C_DISABLED;
end
else
begin
if (debug_csr_write_enable == `TRUE)
begin
if (debug_csr == `LM32_CSR_DC)
wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2];
if (debug_csr == `LM32_CSR_WP0 + i)
wp[i] <= debug_csr_write_data;
end
end
end
end
endgenerate
// Remap exceptions control bit
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
dc_re <= `FALSE;
else
begin
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
dc_re <= debug_csr_write_data[1];
end
end
`ifdef LM32_SINGLE_STEP_ENABLED
// Single-step control flag
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
state <= `LM32_DEBUG_SS_STATE_IDLE;
dc_ss <= `FALSE;
end
else
begin
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
begin
dc_ss <= debug_csr_write_data[0];
if (debug_csr_write_data[0] == `FALSE)
state <= `LM32_DEBUG_SS_STATE_IDLE;
else
state <= `LM32_DEBUG_SS_STATE_WAIT_FOR_RET;
end
case (state)
`LM32_DEBUG_SS_STATE_WAIT_FOR_RET:
begin
// Wait for eret or bret instruction to be executed
if ( ( (eret_q_x == `TRUE)
|| (bret_q_x == `TRUE)
)
&& (stall_x == `FALSE)
)
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
end
`LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN:
begin
// Wait for an instruction to be executed
if ((q_x == `TRUE) && (stall_x == `FALSE))
state <= `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
end
`LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT:
begin
// Wait for exception to be raised
`ifdef CFG_DCACHE_ENABLED
if (dcache_refill_request == `TRUE)
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
else
`endif
if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE))
begin
dc_ss <= `FALSE;
state <= `LM32_DEBUG_SS_STATE_RESTART;
end
end
`LM32_DEBUG_SS_STATE_RESTART:
begin
// Watch to see if stepped instruction is restarted due to a cache miss
`ifdef CFG_DCACHE_ENABLED
if (dcache_refill_request == `TRUE)
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
else
`endif
state <= `LM32_DEBUG_SS_STATE_IDLE;
end
endcase
end
end
`endif
endmodule
`endif

View File

@@ -0,0 +1,564 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_decoder.v
// Title : Instruction decoder
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
// Index of opcode field in an instruction
`define LM32_OPCODE_RNG 31:26
`define LM32_OP_RNG 30:26
// Opcodes - Some are only listed as 5 bits as their MSB is a don't care
`define LM32_OPCODE_ADD 5'b01101
`define LM32_OPCODE_AND 5'b01000
`define LM32_OPCODE_ANDHI 6'b011000
`define LM32_OPCODE_B 6'b110000
`define LM32_OPCODE_BI 6'b111000
`define LM32_OPCODE_BE 6'b010001
`define LM32_OPCODE_BG 6'b010010
`define LM32_OPCODE_BGE 6'b010011
`define LM32_OPCODE_BGEU 6'b010100
`define LM32_OPCODE_BGU 6'b010101
`define LM32_OPCODE_BNE 6'b010111
`define LM32_OPCODE_CALL 6'b110110
`define LM32_OPCODE_CALLI 6'b111110
`define LM32_OPCODE_CMPE 5'b11001
`define LM32_OPCODE_CMPG 5'b11010
`define LM32_OPCODE_CMPGE 5'b11011
`define LM32_OPCODE_CMPGEU 5'b11100
`define LM32_OPCODE_CMPGU 5'b11101
`define LM32_OPCODE_CMPNE 5'b11111
`define LM32_OPCODE_DIVU 6'b100011
`define LM32_OPCODE_LB 6'b000100
`define LM32_OPCODE_LBU 6'b010000
`define LM32_OPCODE_LH 6'b000111
`define LM32_OPCODE_LHU 6'b001011
`define LM32_OPCODE_LW 6'b001010
`define LM32_OPCODE_MODU 6'b110001
`define LM32_OPCODE_MUL 5'b00010
`define LM32_OPCODE_NOR 5'b00001
`define LM32_OPCODE_OR 5'b01110
`define LM32_OPCODE_ORHI 6'b011110
`define LM32_OPCODE_RAISE 6'b101011
`define LM32_OPCODE_RCSR 6'b100100
`define LM32_OPCODE_SB 6'b001100
`define LM32_OPCODE_SEXTB 6'b101100
`define LM32_OPCODE_SEXTH 6'b110111
`define LM32_OPCODE_SH 6'b000011
`define LM32_OPCODE_SL 5'b01111
`define LM32_OPCODE_SR 5'b00101
`define LM32_OPCODE_SRU 5'b00000
`define LM32_OPCODE_SUB 6'b110010
`define LM32_OPCODE_SW 6'b010110
`define LM32_OPCODE_USER 6'b110011
`define LM32_OPCODE_WCSR 6'b110100
`define LM32_OPCODE_XNOR 5'b01001
`define LM32_OPCODE_XOR 5'b00110
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_decoder (
// ----- Inputs -------
instruction,
// ----- Outputs -------
d_result_sel_0,
d_result_sel_1,
x_result_sel_csr,
`ifdef LM32_MC_ARITHMETIC_ENABLED
x_result_sel_mc_arith,
`endif
`ifdef LM32_NO_BARREL_SHIFT
x_result_sel_shift,
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
x_result_sel_sext,
`endif
x_result_sel_logic,
`ifdef CFG_USER_ENABLED
x_result_sel_user,
`endif
x_result_sel_add,
m_result_sel_compare,
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
m_result_sel_shift,
`endif
w_result_sel_load,
`ifdef CFG_PL_MULTIPLY_ENABLED
w_result_sel_mul,
`endif
x_bypass_enable,
m_bypass_enable,
read_enable_0,
read_idx_0,
read_enable_1,
read_idx_1,
write_enable,
write_idx,
immediate,
branch_offset,
load,
store,
size,
sign_extend,
adder_op,
logic_op,
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
direction,
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
shift_left,
shift_right,
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
multiply,
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
divide,
modulus,
`endif
branch,
branch_reg,
condition,
`ifdef CFG_DEBUG_ENABLED
break,
`endif
scall,
eret,
`ifdef CFG_DEBUG_ENABLED
bret,
`endif
`ifdef CFG_USER_ENABLED
user_opcode,
`endif
csr_write_enable
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input [`LM32_INSTRUCTION_RNG] instruction; // Instruction to decode
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0;
reg [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0;
output [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1;
reg [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1;
output x_result_sel_csr;
reg x_result_sel_csr;
`ifdef LM32_MC_ARITHMETIC_ENABLED
output x_result_sel_mc_arith;
reg x_result_sel_mc_arith;
`endif
`ifdef LM32_NO_BARREL_SHIFT
output x_result_sel_shift;
reg x_result_sel_shift;
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
output x_result_sel_sext;
reg x_result_sel_sext;
`endif
output x_result_sel_logic;
reg x_result_sel_logic;
`ifdef CFG_USER_ENABLED
output x_result_sel_user;
reg x_result_sel_user;
`endif
output x_result_sel_add;
reg x_result_sel_add;
output m_result_sel_compare;
reg m_result_sel_compare;
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
output m_result_sel_shift;
reg m_result_sel_shift;
`endif
output w_result_sel_load;
reg w_result_sel_load;
`ifdef CFG_PL_MULTIPLY_ENABLED
output w_result_sel_mul;
reg w_result_sel_mul;
`endif
output x_bypass_enable;
wire x_bypass_enable;
output m_bypass_enable;
wire m_bypass_enable;
output read_enable_0;
wire read_enable_0;
output [`LM32_REG_IDX_RNG] read_idx_0;
wire [`LM32_REG_IDX_RNG] read_idx_0;
output read_enable_1;
wire read_enable_1;
output [`LM32_REG_IDX_RNG] read_idx_1;
wire [`LM32_REG_IDX_RNG] read_idx_1;
output write_enable;
wire write_enable;
output [`LM32_REG_IDX_RNG] write_idx;
wire [`LM32_REG_IDX_RNG] write_idx;
output [`LM32_WORD_RNG] immediate;
wire [`LM32_WORD_RNG] immediate;
output [`LM32_PC_RNG] branch_offset;
wire [`LM32_PC_RNG] branch_offset;
output load;
wire load;
output store;
wire store;
output [`LM32_SIZE_RNG] size;
wire [`LM32_SIZE_RNG] size;
output sign_extend;
wire sign_extend;
output adder_op;
wire adder_op;
output [`LM32_LOGIC_OP_RNG] logic_op;
wire [`LM32_LOGIC_OP_RNG] logic_op;
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
output direction;
wire direction;
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
output shift_left;
wire shift_left;
output shift_right;
wire shift_right;
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
output multiply;
wire multiply;
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
output divide;
wire divide;
output modulus;
wire modulus;
`endif
output branch;
wire branch;
output branch_reg;
wire branch_reg;
output [`LM32_CONDITION_RNG] condition;
wire [`LM32_CONDITION_RNG] condition;
`ifdef CFG_DEBUG_ENABLED
output break;
wire break;
`endif
output scall;
wire scall;
output eret;
wire eret;
`ifdef CFG_DEBUG_ENABLED
output bret;
wire bret;
`endif
`ifdef CFG_USER_ENABLED
output [`LM32_USER_OPCODE_RNG] user_opcode;
wire [`LM32_USER_OPCODE_RNG] user_opcode;
`endif
output csr_write_enable;
wire csr_write_enable;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire [`LM32_WORD_RNG] extended_immediate; // Zero or sign extended immediate
wire [`LM32_WORD_RNG] high_immediate; // Immediate as high 16 bits
wire [`LM32_WORD_RNG] call_immediate; // Call immediate
wire [`LM32_WORD_RNG] branch_immediate; // Conditional branch immediate
wire sign_extend_immediate; // Whether the immediate should be sign extended (`TRUE) or zero extended (`FALSE)
wire select_high_immediate; // Whether to select the high immediate
wire select_call_immediate; // Whether to select the call immediate
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Determine opcode
wire op_add = instruction[`LM32_OP_RNG] == `LM32_OPCODE_ADD;
wire op_and = instruction[`LM32_OP_RNG] == `LM32_OPCODE_AND;
wire op_andhi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_ANDHI;
wire op_b = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_B;
wire op_bi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BI;
wire op_be = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BE;
wire op_bg = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BG;
wire op_bge = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGE;
wire op_bgeu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGEU;
wire op_bgu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGU;
wire op_bne = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BNE;
wire op_call = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_CALL;
wire op_calli = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_CALLI;
wire op_cmpe = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPE;
wire op_cmpg = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPG;
wire op_cmpge = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGE;
wire op_cmpgeu = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGEU;
wire op_cmpgu = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGU;
wire op_cmpne = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPNE;
`ifdef CFG_MC_DIVIDE_ENABLED
wire op_divu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_DIVU;
`endif
wire op_lb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LB;
wire op_lbu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LBU;
wire op_lh = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LH;
wire op_lhu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LHU;
wire op_lw = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LW;
`ifdef CFG_MC_DIVIDE_ENABLED
wire op_modu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_MODU;
`endif
`ifdef LM32_MULTIPLY_ENABLED
wire op_mul = instruction[`LM32_OP_RNG] == `LM32_OPCODE_MUL;
`endif
wire op_nor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_NOR;
wire op_or = instruction[`LM32_OP_RNG] == `LM32_OPCODE_OR;
wire op_orhi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_ORHI;
wire op_raise = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_RAISE;
wire op_rcsr = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_RCSR;
wire op_sb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SB;
`ifdef CFG_SIGN_EXTEND_ENABLED
wire op_sextb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SEXTB;
wire op_sexth = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SEXTH;
`endif
wire op_sh = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SH;
`ifdef LM32_BARREL_SHIFT_ENABLED
wire op_sl = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SL;
`endif
wire op_sr = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SR;
wire op_sru = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SRU;
wire op_sub = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SUB;
wire op_sw = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SW;
wire op_user = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_USER;
wire op_wcsr = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_WCSR;
wire op_xnor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_XNOR;
wire op_xor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_XOR;
// Group opcodes by function
wire arith = op_add | op_sub;
wire logicc = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor;
wire cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne;
wire bra = op_b | op_bi | op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne;
wire call = op_call | op_calli;
`ifdef LM32_BARREL_SHIFT_ENABLED
wire shift = op_sl | op_sr | op_sru;
`endif
`ifdef LM32_NO_BARREL_SHIFT
wire shift = op_sr | op_sru;
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
assign shift_left = op_sl;
assign shift_right = op_sr | op_sru;
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
wire sext = op_sextb | op_sexth;
`endif
`ifdef LM32_MULTIPLY_ENABLED
wire multiply = op_mul;
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
assign divide = op_divu;
assign modulus = op_modu;
`endif
assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw;
assign store = op_sb | op_sh | op_sw;
// Select pipeline multiplexor controls
always @*
begin
// D stage
if (call)
d_result_sel_0 = `LM32_D_RESULT_SEL_0_NEXT_PC;
else
d_result_sel_0 = `LM32_D_RESULT_SEL_0_REG_0;
if (call)
d_result_sel_1 = `LM32_D_RESULT_SEL_1_ZERO;
else if ((instruction[31] == 1'b0) && !bra)
d_result_sel_1 = `LM32_D_RESULT_SEL_1_IMMEDIATE;
else
d_result_sel_1 = `LM32_D_RESULT_SEL_1_REG_1;
// X stage
x_result_sel_csr = `FALSE;
`ifdef LM32_MC_ARITHMETIC_ENABLED
x_result_sel_mc_arith = `FALSE;
`endif
`ifdef LM32_NO_BARREL_SHIFT
x_result_sel_shift = `FALSE;
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
x_result_sel_sext = `FALSE;
`endif
x_result_sel_logic = `FALSE;
`ifdef CFG_USER_ENABLED
x_result_sel_user = `FALSE;
`endif
x_result_sel_add = `FALSE;
if (op_rcsr)
x_result_sel_csr = `TRUE;
`ifdef LM32_MC_ARITHMETIC_ENABLED
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
else if (shift_left | shift_right)
x_result_sel_mc_arith = `TRUE;
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
else if (divide | modulus)
x_result_sel_mc_arith = `TRUE;
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
else if (multiply)
x_result_sel_mc_arith = `TRUE;
`endif
`endif
`ifdef LM32_NO_BARREL_SHIFT
else if (shift)
x_result_sel_shift = `TRUE;
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
else if (sext)
x_result_sel_sext = `TRUE;
`endif
else if (logicc)
x_result_sel_logic = `TRUE;
`ifdef CFG_USER_ENABLED
else if (op_user)
x_result_sel_user = `TRUE;
`endif
else
x_result_sel_add = `TRUE;
// M stage
m_result_sel_compare = cmp;
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
m_result_sel_shift = shift;
`endif
// W stage
w_result_sel_load = load;
`ifdef CFG_PL_MULTIPLY_ENABLED
w_result_sel_mul = op_mul;
`endif
end
// Set if result is valid at end of X stage
assign x_bypass_enable = arith
| logicc
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
| shift_left
| shift_right
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
| multiply
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
| divide
| modulus
`endif
`ifdef LM32_NO_BARREL_SHIFT
| shift
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
| sext
`endif
`ifdef CFG_USER_ENABLED
| op_user
`endif
| op_rcsr
;
// Set if result is valid at end of M stage
assign m_bypass_enable = x_bypass_enable
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
| shift
`endif
| cmp
;
// Register file read port 0
assign read_enable_0 = ~(op_bi | op_calli);
assign read_idx_0 = instruction[25:21];
// Register file read port 1
assign read_enable_1 = ~(op_bi | op_calli | load);
assign read_idx_1 = instruction[20:16];
// Register file write port
assign write_enable = ~(bra | op_raise | store | op_wcsr);
assign write_idx = call
? 5'd29
: instruction[31] == 1'b0
? instruction[20:16]
: instruction[15:11];
// Size of load/stores
assign size = instruction[27:26];
// Whether to sign or zero extend
assign sign_extend = instruction[28];
// Set adder_op to 1 to perform a subtraction
assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra;
// Logic operation (and, or, etc)
assign logic_op = instruction[29:26];
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
// Shift direction
assign direction = instruction[29];
`endif
// Control flow microcodes
assign branch = bra | call;
assign branch_reg = op_call | op_b;
assign condition = instruction[28:26];
`ifdef CFG_DEBUG_ENABLED
assign break = op_raise & ~instruction[2];
`endif
assign scall = op_raise & instruction[2];
assign eret = op_b & (instruction[25:21] == 5'd30);
`ifdef CFG_DEBUG_ENABLED
assign bret = op_b & (instruction[25:21] == 5'd31);
`endif
`ifdef CFG_USER_ENABLED
// Extract user opcode
assign user_opcode = instruction[10:0];
`endif
// CSR read/write
assign csr_write_enable = op_wcsr;
// Extract immediate from instruction
assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor);
assign select_high_immediate = op_andhi | op_orhi;
assign select_call_immediate = instruction[31];
assign high_immediate = {instruction[15:0], 16'h0000};
assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]};
assign call_immediate = {{6{instruction[25]}}, instruction[25:0]};
assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]};
assign immediate = select_high_immediate == `TRUE
? high_immediate
: extended_immediate;
assign branch_offset = select_call_immediate == `TRUE
? call_immediate
: branch_immediate;
endmodule

View File

@@ -0,0 +1,29 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_functions.v
// Title : Common functions
// Version : 6.1.17
// =============================================================================
function integer clogb2;
input [31:0] value;
begin
for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
value = value >> 1;
end
endfunction

View File

@@ -0,0 +1,428 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_icache.v
// Title : Instruction cache
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
`define LM32_IC_ADDR_OFFSET_RNG addr_offset_msb:addr_offset_lsb
`define LM32_IC_ADDR_SET_RNG addr_set_msb:addr_set_lsb
`define LM32_IC_ADDR_TAG_RNG addr_tag_msb:addr_tag_lsb
`define LM32_IC_ADDR_IDX_RNG addr_set_msb:addr_offset_lsb
`define LM32_IC_TMEM_ADDR_WIDTH addr_set_width
`define LM32_IC_TMEM_ADDR_RNG (`LM32_IC_TMEM_ADDR_WIDTH-1):0
`define LM32_IC_DMEM_ADDR_WIDTH (addr_offset_width+addr_set_width)
`define LM32_IC_DMEM_ADDR_RNG (`LM32_IC_DMEM_ADDR_WIDTH-1):0
`define LM32_IC_TAGS_WIDTH (addr_tag_width+1)
`define LM32_IC_TAGS_RNG (`LM32_IC_TAGS_WIDTH-1):0
`define LM32_IC_TAGS_TAG_RNG (`LM32_IC_TAGS_WIDTH-1):1
`define LM32_IC_TAGS_VALID_RNG 0
`define LM32_IC_STATE_RNG 3:0
`define LM32_IC_STATE_FLUSH_INIT 4'b0001
`define LM32_IC_STATE_FLUSH 4'b0010
`define LM32_IC_STATE_CHECK 4'b0100
`define LM32_IC_STATE_REFILL 4'b1000
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_icache (
// ----- Inputs -----
clk_i,
rst_i,
stall_a,
stall_f,
address_a,
address_f,
read_enable_f,
refill_ready,
refill_data,
iflush,
// ----- Outputs -----
stall_request,
restart_request,
refill_request,
refill_address,
refilling,
inst
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter associativity = 1; // Associativity of the cache (Number of ways)
parameter sets = 512; // Number of sets
parameter bytes_per_line = 16; // Number of bytes per cache line
parameter base_address = 0; // Base address of cachable memory
parameter limit = 0; // Limit (highest address) of cachable memory
localparam addr_offset_width = 2;
localparam addr_set_width = 9;
localparam addr_offset_lsb = 2;
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
localparam addr_set_lsb = (addr_offset_msb+1);
localparam addr_set_msb = (addr_set_lsb+addr_set_width-1);
localparam addr_tag_lsb = (addr_set_msb+1);
localparam addr_tag_msb = 31;
localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_a; // Stall instruction in A stage
input stall_f; // Stall instruction in F stage
input [`LM32_PC_RNG] address_a; // Address of instruction in A stage
input [`LM32_PC_RNG] address_f; // Address of instruction in F stage
input read_enable_f; // Indicates if cache access is valid
input refill_ready; // Next word of refill data is ready
input [`LM32_INSTRUCTION_RNG] refill_data; // Data to refill the cache with
input iflush; // Flush the cache
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output stall_request; // Request to stall the pipeline
wire stall_request;
output restart_request; // Request to restart instruction that caused the cache miss
reg restart_request;
output refill_request; // Request to refill a cache line
wire refill_request;
output [`LM32_PC_RNG] refill_address; // Base address of cache refill
reg [`LM32_PC_RNG] refill_address;
output refilling; // Indicates the instruction cache is currently refilling
reg refilling;
output [`LM32_INSTRUCTION_RNG] inst; // Instruction read from cache
wire [`LM32_INSTRUCTION_RNG] inst;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire enable;
wire [0:associativity-1] way_mem_we;
wire [`LM32_INSTRUCTION_RNG] way_data[0:associativity-1];
wire [`LM32_IC_TAGS_TAG_RNG] way_tag[0:associativity-1];
wire [0:associativity-1] way_valid;
wire [0:associativity-1] way_match;
wire miss;
wire [`LM32_IC_TMEM_ADDR_RNG] tmem_read_address;
wire [`LM32_IC_TMEM_ADDR_RNG] tmem_write_address;
wire [`LM32_IC_DMEM_ADDR_RNG] dmem_read_address;
wire [`LM32_IC_DMEM_ADDR_RNG] dmem_write_address;
wire [`LM32_IC_TAGS_RNG] tmem_write_data;
reg [`LM32_IC_STATE_RNG] state;
wire flushing;
wire check;
wire refill;
reg [associativity-1:0] refill_way_select;
reg [`LM32_IC_ADDR_OFFSET_RNG] refill_offset;
wire last_refill;
reg [`LM32_IC_TMEM_ADDR_RNG] flush_set;
genvar i;
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
generate
for (i = 0; i < associativity; i = i + 1)
begin : memories
// Way 0 data
lm32_ram #(
// ----- Parameters -------
.data_width (32),
.address_width (`LM32_IC_DMEM_ADDR_WIDTH)
) way_0_data_ram (
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (dmem_read_address),
.enable_read (enable),
.write_address (dmem_write_address),
.enable_write (`TRUE),
.write_enable (way_mem_we[i]),
.write_data (refill_data),
// ----- Outputs -------
.read_data (way_data[i])
);
// Way 0 tags
lm32_ram #(
// ----- Parameters -------
.data_width (`LM32_IC_TAGS_WIDTH),
.address_width (`LM32_IC_TMEM_ADDR_WIDTH)
) way_0_tag_ram (
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (tmem_read_address),
.enable_read (enable),
.write_address (tmem_write_address),
.enable_write (`TRUE),
.write_enable (way_mem_we[i] | flushing),
.write_data (tmem_write_data),
// ----- Outputs -------
.read_data ({way_tag[i], way_valid[i]})
);
end
endgenerate
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Compute which ways in the cache match the address address being read
generate
for (i = 0; i < associativity; i = i + 1)
begin : match
assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[`LM32_IC_ADDR_TAG_RNG], `TRUE});
end
endgenerate
// Select data from way that matched the address being read
generate
if (associativity == 1)
begin : inst_1
assign inst = way_data[0];
end
else if (associativity == 2)
begin : inst_2
assign inst = way_match[0] ? way_data[0] : way_data[1];
end
endgenerate
// Compute address to use to index into the data memories
generate
if (bytes_per_line > 4)
begin : wadr1
assign dmem_write_address = {refill_address[`LM32_IC_ADDR_SET_RNG], refill_offset};
end
else
begin : wadr2
assign dmem_write_address = refill_address[`LM32_IC_ADDR_SET_RNG];
end
endgenerate
assign dmem_read_address = address_a[`LM32_IC_ADDR_IDX_RNG];
// Compute address to use to index into the tag memories
assign tmem_read_address = address_a[`LM32_IC_ADDR_SET_RNG];
assign tmem_write_address = flushing
? flush_set
: refill_address[`LM32_IC_ADDR_SET_RNG];
// Compute signal to indicate when we are on the last refill accesses
generate
if (bytes_per_line > 4)
begin : lrefil1
assign last_refill = refill_offset == {addr_offset_width{1'b1}};
end
else
begin : lrefil2
assign last_refill = `TRUE;
end
endgenerate
// Compute data and tag memory access enable
assign enable = (stall_a == `FALSE);
// Compute data and tag memory write enables
generate
if (associativity == 1)
begin : we_1
assign way_mem_we[0] = (refill_ready == `TRUE);
end
else
begin : we_2
assign way_mem_we[0] = (refill_ready == `TRUE) && (refill_way_select[0] == `TRUE);
assign way_mem_we[1] = (refill_ready == `TRUE) && (refill_way_select[1] == `TRUE);
end
endgenerate
// On the last refill cycle set the valid bit, for all other writes it should be cleared
assign tmem_write_data[`LM32_IC_TAGS_VALID_RNG] = last_refill & !flushing;
assign tmem_write_data[`LM32_IC_TAGS_TAG_RNG] = refill_address[`LM32_IC_ADDR_TAG_RNG];
// Signals that indicate which state we are in
assign flushing = |state[1:0];
assign check = state[2];
assign refill = state[3];
assign miss = (~(|way_match)) && (read_enable_f == `TRUE) && (stall_f == `FALSE);
assign stall_request = (check == `FALSE);
assign refill_request = (refill == `TRUE);
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
// Record way selected for replacement on a cache miss
generate
if (associativity >= 2)
begin : way_select
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
refill_way_select <= {{associativity-1{1'b0}}, 1'b1};
else
begin
if (miss == `TRUE)
refill_way_select <= {refill_way_select[0], refill_way_select[1]};
end
end
end
endgenerate
// Record whether we are refilling
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
refilling <= `FALSE;
else
refilling <= refill;
end
// Instruction cache control FSM
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
state <= `LM32_IC_STATE_FLUSH_INIT;
flush_set <= {`LM32_IC_TMEM_ADDR_WIDTH{1'b1}};
refill_address <= {`LM32_PC_WIDTH{1'bx}};
restart_request <= `FALSE;
end
else
begin
case (state)
// Flush the cache for the first time after reset
`LM32_IC_STATE_FLUSH_INIT:
begin
if (flush_set == {`LM32_IC_TMEM_ADDR_WIDTH{1'b0}})
state <= `LM32_IC_STATE_CHECK;
flush_set <= flush_set - 1'b1;
end
// Flush the cache in response to an write to the ICC CSR
`LM32_IC_STATE_FLUSH:
begin
if (flush_set == {`LM32_IC_TMEM_ADDR_WIDTH{1'b0}})
state <= `LM32_IC_STATE_REFILL;
flush_set <= flush_set - 1'b1;
end
// Check for cache misses
`LM32_IC_STATE_CHECK:
begin
if (stall_a == `FALSE)
restart_request <= `FALSE;
if (iflush == `TRUE)
begin
refill_address <= address_f;
state <= `LM32_IC_STATE_FLUSH;
end
else if (miss == `TRUE)
begin
refill_address <= address_f;
state <= `LM32_IC_STATE_REFILL;
end
end
// Refill a cache line
`LM32_IC_STATE_REFILL:
begin
if (refill_ready == `TRUE)
begin
if (last_refill == `TRUE)
begin
restart_request <= `TRUE;
state <= `LM32_IC_STATE_CHECK;
end
end
end
endcase
end
end
generate
if (bytes_per_line > 4)
begin : refilof1
// Refill offset
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
refill_offset <= {addr_offset_width{1'b0}};
else
begin
case (state)
// Check for cache misses
`LM32_IC_STATE_CHECK:
begin
if (iflush == `TRUE)
refill_offset <= {addr_offset_width{1'b0}};
else if (miss == `TRUE)
refill_offset <= {addr_offset_width{1'b0}};
end
// Refill a cache line
`LM32_IC_STATE_REFILL:
begin
if (refill_ready == `TRUE)
refill_offset <= refill_offset + 1'b1;
end
endcase
end
end
end
endgenerate
endmodule

View File

@@ -0,0 +1,320 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_include.v
// Title : CPU global macros
// Version : 6.1.17
// =============================================================================
`ifdef LM32_INCLUDE_V
`else
`define LM32_INCLUDE_V
// Configuration options
`include "system_conf.v"
`ifdef TRUE
`else
`define TRUE 1'b1
`define FALSE 1'b0
`define TRUE_N 1'b0
`define FALSE_N 1'b1
`endif
// Wishbone configuration
`define CFG_IWB_ENABLED
`define CFG_DWB_ENABLED
// Data-path width
`define LM32_WORD_WIDTH 32
`define LM32_WORD_RNG (`LM32_WORD_WIDTH-1):0
`define LM32_SHIFT_WIDTH 5
`define LM32_SHIFT_RNG (`LM32_SHIFT_WIDTH-1):0
`define LM32_BYTE_SELECT_WIDTH 4
`define LM32_BYTE_SELECT_RNG (`LM32_BYTE_SELECT_WIDTH-1):0
// Register file size
`define LM32_REGISTERS 32
`define LM32_REG_IDX_WIDTH 5
`define LM32_REG_IDX_RNG (`LM32_REG_IDX_WIDTH-1):0
// Standard register numbers
`define LM32_RA_REG `LM32_REG_IDX_WIDTH'd29
`define LM32_EA_REG `LM32_REG_IDX_WIDTH'd30
`define LM32_BA_REG `LM32_REG_IDX_WIDTH'd31
// Range of Program Counter. Two LSBs are always 0.
`ifdef CFG_ICACHE_ENABLED
// XXX `define LM32_PC_WIDTH (clogb2(`CFG_ICACHE_LIMIT-`CFG_ICACHE_BASE_ADDRESS)-2) XXX
`define LM32_PC_WIDTH 30
`else
`ifdef CFG_IWB_ENABLED
`define LM32_PC_WIDTH (`LM32_WORD_WIDTH-2)
`else
`define LM32_PC_WIDTH `LM32_IROM_ADDRESS_WIDTH
`endif
`endif
`define LM32_PC_RNG (`LM32_PC_WIDTH+2-1):2
// Range of an instruction
`define LM32_INSTRUCTION_WIDTH 32
`define LM32_INSTRUCTION_RNG (`LM32_INSTRUCTION_WIDTH-1):0
// Adder operation
`define LM32_ADDER_OP_ADD 1'b0
`define LM32_ADDER_OP_SUBTRACT 1'b1
// Shift direction
`define LM32_SHIFT_OP_RIGHT 1'b0
`define LM32_SHIFT_OP_LEFT 1'b1
// Currently always enabled
`define CFG_BUS_ERRORS_ENABLED
// Derive macro that indicates whether we have single-stepping or not
`ifdef CFG_ROM_DEBUG_ENABLED
`define LM32_SINGLE_STEP_ENABLED
`else
`ifdef CFG_HW_DEBUG_ENABLED
`define LM32_SINGLE_STEP_ENABLED
`endif
`endif
// Derive macro that indicates whether JTAG interface is required
`ifdef CFG_JTAG_UART_ENABLED
`define LM32_JTAG_ENABLED
`else
`ifdef CFG_DEBUG_ENABLED
`define LM32_JTAG_ENABLED
`else
`endif
`endif
// Derive macro that indicates whether we have a barrel-shifter or not
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
`define LM32_BARREL_SHIFT_ENABLED
`else // CFG_PL_BARREL_SHIFT_ENABLED
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
`define LM32_BARREL_SHIFT_ENABLED
`else
`define LM32_NO_BARREL_SHIFT
`endif
`endif // CFG_PL_BARREL_SHIFT_ENABLED
// Derive macro that indicates whether we have a multiplier or not
`ifdef CFG_PL_MULTIPLY_ENABLED
`define LM32_MULTIPLY_ENABLED
`else
`ifdef CFG_MC_MULTIPLY_ENABLED
`define LM32_MULTIPLY_ENABLED
`endif
`endif
// Derive a macro that indicates whether or not the multi-cycle arithmetic unit is required
`ifdef CFG_MC_DIVIDE_ENABLED
`define LM32_MC_ARITHMETIC_ENABLED
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
`define LM32_MC_ARITHMETIC_ENABLED
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
`define LM32_MC_ARITHMETIC_ENABLED
`endif
// Derive macro that indicates if we are using an EBR register file
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
`define LM32_EBR_REGISTER_FILE
`endif
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
`define LM32_EBR_REGISTER_FILE
`endif
// Revision number
`define LM32_REVISION 6'h11
// Logical operations - Function encoded directly in instruction
`define LM32_LOGIC_OP_RNG 3:0
// Conditions for conditional branches
`define LM32_CONDITION_WIDTH 3
`define LM32_CONDITION_RNG (`LM32_CONDITION_WIDTH-1):0
`define LM32_CONDITION_E 3'b001
`define LM32_CONDITION_G 3'b010
`define LM32_CONDITION_GE 3'b011
`define LM32_CONDITION_GEU 3'b100
`define LM32_CONDITION_GU 3'b101
`define LM32_CONDITION_NE 3'b111
`define LM32_CONDITION_U1 3'b000
`define LM32_CONDITION_U2 3'b110
// Size of load or store instruction - Encoding corresponds to opcode
`define LM32_SIZE_WIDTH 2
`define LM32_SIZE_RNG 1:0
`define LM32_SIZE_BYTE 2'b00
`define LM32_SIZE_HWORD 2'b11
`define LM32_SIZE_WORD 2'b10
`define LM32_ADDRESS_LSBS_WIDTH 2
// Width and range of a CSR index
`ifdef CFG_DEBUG_ENABLED
`define LM32_CSR_WIDTH 5
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
`else
`ifdef CFG_JTAG_ENABLED
`define LM32_CSR_WIDTH 4
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
`else
`define LM32_CSR_WIDTH 3
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
`endif
`endif
// CSR indices
`define LM32_CSR_IE `LM32_CSR_WIDTH'h0
`define LM32_CSR_IM `LM32_CSR_WIDTH'h1
`define LM32_CSR_IP `LM32_CSR_WIDTH'h2
`define LM32_CSR_ICC `LM32_CSR_WIDTH'h3
`define LM32_CSR_DCC `LM32_CSR_WIDTH'h4
`define LM32_CSR_CC `LM32_CSR_WIDTH'h5
`define LM32_CSR_CFG `LM32_CSR_WIDTH'h6
`define LM32_CSR_EBA `LM32_CSR_WIDTH'h7
`ifdef CFG_DEBUG_ENABLED
`define LM32_CSR_DC `LM32_CSR_WIDTH'h8
`define LM32_CSR_DEBA `LM32_CSR_WIDTH'h9
`endif
`ifdef CFG_JTAG_ENABLED
`define LM32_CSR_JTX `LM32_CSR_WIDTH'he
`define LM32_CSR_JRX `LM32_CSR_WIDTH'hf
`endif
`ifdef CFG_DEBUG_ENABLED
`define LM32_CSR_BP0 `LM32_CSR_WIDTH'h10
`define LM32_CSR_BP1 `LM32_CSR_WIDTH'h11
`define LM32_CSR_BP2 `LM32_CSR_WIDTH'h12
`define LM32_CSR_BP3 `LM32_CSR_WIDTH'h13
`define LM32_CSR_WP0 `LM32_CSR_WIDTH'h18
`define LM32_CSR_WP1 `LM32_CSR_WIDTH'h19
`define LM32_CSR_WP2 `LM32_CSR_WIDTH'h1a
`define LM32_CSR_WP3 `LM32_CSR_WIDTH'h1b
`endif
// Values for WPC CSR
`define LM32_WPC_C_RNG 1:0
`define LM32_WPC_C_DISABLED 2'b00
`define LM32_WPC_C_READ 2'b01
`define LM32_WPC_C_WRITE 2'b10
`define LM32_WPC_C_READ_WRITE 2'b11
// Exception IDs
`define LM32_EID_WIDTH 3
`define LM32_EID_RNG (`LM32_EID_WIDTH-1):0
`define LM32_EID_RESET 3'h0
`define LM32_EID_BREAKPOINT 3'd1
`define LM32_EID_INST_BUS_ERROR 3'h2
`define LM32_EID_WATCHPOINT 3'd3
`define LM32_EID_DATA_BUS_ERROR 3'h4
`define LM32_EID_DIVIDE_BY_ZERO 3'h5
`define LM32_EID_INTERRUPT 3'h6
`define LM32_EID_SCALL 3'h7
// Pipeline result selection mux controls
`define LM32_D_RESULT_SEL_0_RNG 0:0
`define LM32_D_RESULT_SEL_0_REG_0 1'b0
`define LM32_D_RESULT_SEL_0_NEXT_PC 1'b1
`define LM32_D_RESULT_SEL_1_RNG 1:0
`define LM32_D_RESULT_SEL_1_ZERO 2'b00
`define LM32_D_RESULT_SEL_1_REG_1 2'b01
`define LM32_D_RESULT_SEL_1_IMMEDIATE 2'b10
`define LM32_USER_OPCODE_WIDTH 11
`define LM32_USER_OPCODE_RNG (`LM32_USER_OPCODE_WIDTH-1):0
// Derive a macro to indicate if either of the caches are implemented
`ifdef CFG_ICACHE_ENABLED
`define LM32_CACHE_ENABLED
`else
`ifdef CFG_DCACHE_ENABLED
`define LM32_CACHE_ENABLED
`endif
`endif
/////////////////////////////////////////////////////
// Interrupts
/////////////////////////////////////////////////////
// Always enable interrupts
`define CFG_INTERRUPTS_ENABLED
// Currently this is fixed to 32 and should not be changed
`define CFG_INTERRUPTS 32
`define LM32_INTERRUPT_WIDTH `CFG_INTERRUPTS
`define LM32_INTERRUPT_RNG (`LM32_INTERRUPT_WIDTH-1):0
/////////////////////////////////////////////////////
// General
/////////////////////////////////////////////////////
// Sub-word range types
`define LM32_BYTE_WIDTH 8
`define LM32_BYTE_RNG 7:0
`define LM32_HWORD_WIDTH 16
`define LM32_HWORD_RNG 15:0
// Word sub-byte indicies
`define LM32_BYTE_0_RNG 7:0
`define LM32_BYTE_1_RNG 15:8
`define LM32_BYTE_2_RNG 23:16
`define LM32_BYTE_3_RNG 31:24
// Word sub-halfword indices
`define LM32_HWORD_0_RNG 15:0
`define LM32_HWORD_1_RNG 31:16
// Use an asynchronous reset
// To use a synchronous reset, define this macro as nothing
`define CFG_RESET_SENSITIVITY or posedge rst_i
// V.T. Srce
`define SRCE
// Whether to include context registers for debug exceptions
// in addition to standard exception handling registers
// Bizarre - Removing this increases LUT count!
`define CFG_DEBUG_EXCEPTIONS_ENABLED
// Wishbone defines
// Refer to Wishbone System-on-Chip Interconnection Architecture
// These should probably be moved to a Wishbone common file
// Wishbone cycle types
`define LM32_CTYPE_WIDTH 3
`define LM32_CTYPE_RNG (`LM32_CTYPE_WIDTH-1):0
`define LM32_CTYPE_CLASSIC 3'b000
`define LM32_CTYPE_CONSTANT 3'b001
`define LM32_CTYPE_INCREMENTING 3'b010
`define LM32_CTYPE_END 3'b111
// Wishbone burst types
`define LM32_BTYPE_WIDTH 2
`define LM32_BTYPE_RNG (`LM32_BTYPE_WIDTH-1):0
`define LM32_BTYPE_LINEAR 2'b00
`define LM32_BTYPE_4_BEAT 2'b01
`define LM32_BTYPE_8_BEAT 2'b10
`define LM32_BTYPE_16_BEAT 2'b11
`endif

View File

@@ -0,0 +1,32 @@
`ifndef LM32_ALL_FILES
`define LM32_ALL_FILES
//`ifndef SIMULATION
//`include "pmi_def.v"
//`endif
// JTAG Debug related files
`include "../components/lm32_top/rtl/verilog/er1.v"
`include "../components/lm32_top/rtl/verilog/typeb.v"
`include "../components/lm32_top/rtl/verilog/typea.v"
`include "../components/lm32_top/rtl/verilog/jtag_cores.v"
`include "../components/lm32_top/rtl/verilog/jtag_lm32.v"
// CPU Core related files
`include "../components/lm32_top/rtl/verilog/lm32_addsub.v"
`include "../components/lm32_top/rtl/verilog/lm32_adder.v"
`include "../components/lm32_top/rtl/verilog/lm32_cpu.v"
`include "../components/lm32_top/rtl/verilog/lm32_dcache.v"
`include "../components/lm32_top/rtl/verilog/lm32_debug.v"
`include "../components/lm32_top/rtl/verilog/lm32_decoder.v"
`include "../components/lm32_top/rtl/verilog/lm32_icache.v"
`include "../components/lm32_top/rtl/verilog/lm32_instruction_unit.v"
`include "../components/lm32_top/rtl/verilog/lm32_interrupt.v"
`include "../components/lm32_top/rtl/verilog/lm32_load_store_unit.v"
`include "../components/lm32_top/rtl/verilog/lm32_logic_op.v"
`include "../components/lm32_top/rtl/verilog/lm32_mc_arithmetic.v"
`include "../components/lm32_top/rtl/verilog/lm32_multiplier.v"
`include "../components/lm32_top/rtl/verilog/lm32_shifter.v"
`include "../components/lm32_top/rtl/verilog/lm32_top.v"
`include "../components/lm32_top/rtl/verilog/lm32_monitor.v"
`include "../components/lm32_top/rtl/verilog/lm32_monitor_ram.v"
`include "../components/lm32_top/rtl/verilog/lm32_ram.v"
`include "../components/lm32_top/rtl/verilog/lm32_jtag.v"
`endif // LM32_ALL_FILES

View File

@@ -0,0 +1,751 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_instruction_unit.v
// Title : Instruction unit
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_instruction_unit (
// ----- Inputs -------
clk_i,
rst_i,
// From pipeline
stall_a,
stall_f,
stall_d,
stall_x,
stall_m,
valid_f,
kill_f,
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
branch_taken_x,
branch_target_x,
`endif
branch_taken_m,
branch_target_m,
`ifdef CFG_ICACHE_ENABLED
iflush,
`endif
`ifdef CFG_DCACHE_ENABLED
dcache_restart_request,
dcache_refill_request,
dcache_refilling,
`endif
`ifdef CFG_IWB_ENABLED
// From Wishbone
i_dat_i,
i_ack_i,
i_err_i,
i_rty_i,
`endif
`ifdef CFG_HW_DEBUG_ENABLED
jtag_read_enable,
jtag_write_enable,
jtag_write_data,
jtag_address,
`endif
// ----- Outputs -------
// To pipeline
pc_f,
pc_d,
pc_x,
pc_m,
pc_w,
`ifdef CFG_ICACHE_ENABLED
icache_stall_request,
icache_restart_request,
icache_refill_request,
icache_refilling,
`endif
`ifdef CFG_IWB_ENABLED
// To Wishbone
i_dat_o,
i_adr_o,
i_cyc_o,
i_sel_o,
i_stb_o,
i_we_o,
i_cti_o,
i_lock_o,
i_bte_o,
`endif
`ifdef CFG_HW_DEBUG_ENABLED
jtag_read_data,
jtag_access_complete,
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_d,
`endif
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
instruction_f,
`endif
instruction_d
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter associativity = 1; // Associativity of the cache (Number of ways)
parameter sets = 512; // Number of sets
parameter bytes_per_line = 16; // Number of bytes per cache line
parameter base_address = 0; // Base address of cachable memory
parameter limit = 0; // Limit (highest address) of cachable memory
// For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
//localparam addr_offset_width = (bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2);
localparam addr_offset_width = 2;
localparam addr_offset_lsb = 2;
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_a; // Stall A stage instruction
input stall_f; // Stall F stage instruction
input stall_d; // Stall D stage instruction
input stall_x; // Stall X stage instruction
input stall_m; // Stall M stage instruction
input valid_f; // Instruction in F stage is valid
input kill_f; // Kill instruction in F stage
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
input branch_taken_x; // Branch instruction in X stage is taken
input [`LM32_PC_RNG] branch_target_x; // Target PC of X stage branch instruction
`endif
input branch_taken_m; // Branch instruction in M stage is taken
input [`LM32_PC_RNG] branch_target_m; // Target PC of M stage branch instruction
`ifdef CFG_ICACHE_ENABLED
input iflush; // Flush instruction cache
`endif
`ifdef CFG_DCACHE_ENABLED
input dcache_restart_request; // Restart instruction that caused a data cache miss
input dcache_refill_request; // Request to refill data cache
input dcache_refilling;
`endif
`ifdef CFG_IWB_ENABLED
input [`LM32_WORD_RNG] i_dat_i; // Instruction Wishbone interface read data
input i_ack_i; // Instruction Wishbone interface acknowledgement
input i_err_i; // Instruction Wishbone interface error
input i_rty_i; // Instruction Wishbone interface retry
`endif
`ifdef CFG_HW_DEBUG_ENABLED
input jtag_read_enable; // JTAG read memory request
input jtag_write_enable; // JTAG write memory request
input [`LM32_BYTE_RNG] jtag_write_data; // JTAG wrirte data
input [`LM32_WORD_RNG] jtag_address; // JTAG read/write address
`endif
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_PC_RNG] pc_f; // F stage PC
reg [`LM32_PC_RNG] pc_f;
output [`LM32_PC_RNG] pc_d; // D stage PC
reg [`LM32_PC_RNG] pc_d;
output [`LM32_PC_RNG] pc_x; // X stage PC
reg [`LM32_PC_RNG] pc_x;
output [`LM32_PC_RNG] pc_m; // M stage PC
reg [`LM32_PC_RNG] pc_m;
output [`LM32_PC_RNG] pc_w; // W stage PC
reg [`LM32_PC_RNG] pc_w;
`ifdef CFG_ICACHE_ENABLED
output icache_stall_request; // Instruction cache stall request
wire icache_stall_request;
output icache_restart_request; // Request to restart instruction that cached instruction cache miss
wire icache_restart_request;
output icache_refill_request; // Instruction cache refill request
wire icache_refill_request;
output icache_refilling; // Indicates the icache is refilling
wire icache_refilling;
`endif
`ifdef CFG_IWB_ENABLED
output [`LM32_WORD_RNG] i_dat_o; // Instruction Wishbone interface write data
`ifdef CFG_HW_DEBUG_ENABLED
reg [`LM32_WORD_RNG] i_dat_o;
`else
wire [`LM32_WORD_RNG] i_dat_o;
`endif
output [`LM32_WORD_RNG] i_adr_o; // Instruction Wishbone interface address
reg [`LM32_WORD_RNG] i_adr_o;
output i_cyc_o; // Instruction Wishbone interface cycle
reg i_cyc_o;
output [`LM32_BYTE_SELECT_RNG] i_sel_o; // Instruction Wishbone interface byte select
`ifdef CFG_HW_DEBUG_ENABLED
reg [`LM32_BYTE_SELECT_RNG] i_sel_o;
`else
wire [`LM32_BYTE_SELECT_RNG] i_sel_o;
`endif
output i_stb_o; // Instruction Wishbone interface strobe
reg i_stb_o;
output i_we_o; // Instruction Wishbone interface write enable
`ifdef CFG_HW_DEBUG_ENABLED
reg i_we_o;
`else
wire i_we_o;
`endif
output [`LM32_CTYPE_RNG] i_cti_o; // Instruction Wishbone interface cycle type
reg [`LM32_CTYPE_RNG] i_cti_o;
output i_lock_o; // Instruction Wishbone interface lock bus
reg i_lock_o;
output [`LM32_BTYPE_RNG] i_bte_o; // Instruction Wishbone interface burst type
wire [`LM32_BTYPE_RNG] i_bte_o;
`endif
`ifdef CFG_HW_DEBUG_ENABLED
output [`LM32_BYTE_RNG] jtag_read_data; // Data read for JTAG interface
reg [`LM32_BYTE_RNG] jtag_read_data;
output jtag_access_complete; // Requested memory access by JTAG interface is complete
wire jtag_access_complete;
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
output bus_error_d; // Indicates a bus error occured while fetching the instruction
reg bus_error_d;
`endif
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
output [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction (only to have register indices extracted from)
wire [`LM32_INSTRUCTION_RNG] instruction_f;
`endif
output [`LM32_INSTRUCTION_RNG] instruction_d; // D stage instruction to be decoded
reg [`LM32_INSTRUCTION_RNG] instruction_d;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [`LM32_PC_RNG] pc_a; // A stage PC
`ifdef LM32_CACHE_ENABLED
reg [`LM32_PC_RNG] restart_address; // Address to restart from after a cache miss
`endif
`ifdef CFG_ICACHE_ENABLED
wire icache_read_enable_f; // Indicates if instruction cache miss is valid
wire [`LM32_PC_RNG] icache_refill_address; // Address that caused cache miss
reg icache_refill_ready; // Indicates when next word of refill data is ready to be written to cache
reg [`LM32_INSTRUCTION_RNG] icache_refill_data; // Next word of refill data, fetched from Wishbone
wire [`LM32_INSTRUCTION_RNG] icache_data_f; // Instruction fetched from instruction cache
wire [`LM32_CTYPE_RNG] first_cycle_type; // First Wishbone cycle type
wire [`LM32_CTYPE_RNG] next_cycle_type; // Next Wishbone cycle type
wire last_word; // Indicates if this is the last word in the cache line
wire [`LM32_PC_RNG] first_address; // First cache refill address
`else
`ifdef CFG_IWB_ENABLED
reg [`LM32_INSTRUCTION_RNG] wb_data_f; // Instruction fetched from Wishbone
`endif
`endif
`ifdef CFG_IROM_ENABLED
wire irom_select_a; // Indicates if A stage PC maps to a ROM address
reg irom_select_f; // Indicates if F stage PC maps to a ROM address
wire [`LM32_INSTRUCTION_RNG] irom_data_f; // Instruction fetched from ROM
`endif
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
`else
wire [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
reg bus_error_f; // Indicates if a bus error occured while fetching the instruction in the F stage
`endif
`ifdef CFG_HW_DEBUG_ENABLED
reg jtag_access; // Indicates if a JTAG WB access is in progress
`endif
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
// Instruction ROM
`ifdef CFG_IROM_ENABLED
pmi_ram_dp #(
// ----- Parameters -------
.pmi_wr_addr_depth (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
.pmi_wr_addr_width ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
.pmi_wr_data_width (`LM32_INSTRUCTION_WIDTH),
.pmi_rd_addr_depth (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
.pmi_rd_addr_width ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
.pmi_rd_data_width (`LM32_INSTRUCTION_WIDTH),
.pmi_regmode ("noreg"),
.pmi_gsr ("enable"),
.pmi_resetmode ("async"),
.pmi_init_file (`CFG_IROM_INIT_FILE),
.pmi_init_file_format ("hex"),
.module_type ("pmi_ram_dp")
) ram (
// ----- Inputs -------
.RdClock (clk_i),
.WrClock (`FALSE),
.Reset (rst_i),
.Data ({32{1'b0}}),
.RdAddress (pc_a[(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)+2-1:2]),
.WrAddress ({(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1){1'b0}}),
.RdClockEn (~stall_a),
.WrClockEn (`FALSE),
.WE (`FALSE),
// ----- Outputs -------
.Q (irom_data_f)
);
`endif
`ifdef CFG_ICACHE_ENABLED
// Instruction cache
lm32_icache #(
.associativity (associativity),
.sets (sets),
.bytes_per_line (bytes_per_line),
.base_address (base_address),
.limit (limit)
) icache (
// ----- Inputs -----
.clk_i (clk_i),
.rst_i (rst_i),
.stall_a (stall_a),
.stall_f (stall_f),
.address_a (pc_a),
.address_f (pc_f),
.read_enable_f (icache_read_enable_f),
.refill_ready (icache_refill_ready),
.refill_data (icache_refill_data),
.iflush (iflush),
// ----- Outputs -----
.stall_request (icache_stall_request),
.restart_request (icache_restart_request),
.refill_request (icache_refill_request),
.refill_address (icache_refill_address),
.refilling (icache_refilling),
.inst (icache_data_f)
);
`endif
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
`ifdef CFG_ICACHE_ENABLED
// Generate signal that indicates when instruction cache misses are valid
assign icache_read_enable_f = (valid_f == `TRUE)
&& (kill_f == `FALSE)
`ifdef CFG_DCACHE_ENABLED
&& (dcache_restart_request == `FALSE)
`endif
`ifdef CFG_IROM_ENABLED
&& (irom_select_f == `FALSE)
`endif
;
`endif
// Compute address of next instruction to fetch
always @(*)
begin
// The request from the latest pipeline stage must take priority
`ifdef CFG_DCACHE_ENABLED
if (dcache_restart_request == `TRUE)
pc_a = restart_address;
else
`endif
if (branch_taken_m == `TRUE)
pc_a = branch_target_m;
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
else if (branch_taken_x == `TRUE)
pc_a = branch_target_x;
`endif
else
`ifdef CFG_ICACHE_ENABLED
if (icache_restart_request == `TRUE)
pc_a = restart_address;
else
`endif
pc_a = pc_f + 1'b1;
end
// Select where instruction should be fetched from
`ifdef CFG_IROM_ENABLED
assign irom_select_a = ({pc_a, 2'b00} >= `CFG_IROM_BASE_ADDRESS) && ({pc_a, 2'b00} <= `CFG_IROM_LIMIT);
`endif
// Select instruction from selected source
`ifdef CFG_ICACHE_ENABLED
`ifdef CFG_IROM_ENABLED
assign instruction_f = irom_select_f == `TRUE ? irom_data_f : icache_data_f;
`else
assign instruction_f = icache_data_f;
`endif
`else
`ifdef CFG_IROM_ENABLED
`ifdef CFG_IWB_ENABLED
assign instruction_f = irom_select_f == `TRUE ? irom_data_f : wb_data_f;
`else
assign instruction_f = irom_data_f;
`endif
`else
assign instruction_f = wb_data_f;
`endif
`endif
// Unused/constant Wishbone signals
`ifdef CFG_IWB_ENABLED
`ifdef CFG_HW_DEBUG_ENABLED
`else
assign i_dat_o = 32'd0;
assign i_we_o = `FALSE;
assign i_sel_o = 4'b1111;
`endif
assign i_bte_o = `LM32_BTYPE_LINEAR;
`endif
`ifdef CFG_ICACHE_ENABLED
// Determine parameters for next cache refill Wishbone access
// generate
// case (bytes_per_line)
// 4:
// begin
// assign first_cycle_type = `LM32_CTYPE_END;
// assign next_cycle_type = `LM32_CTYPE_END;
// assign last_word = `TRUE;
// assign first_address = icache_refill_address;
// end
// 8:
// begin
// assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
// assign next_cycle_type = `LM32_CTYPE_END;
// assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1;
// assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
// end
// 16:
// begin
assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? `LM32_CTYPE_END : `LM32_CTYPE_INCREMENTING;
assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11;
assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
// end
// endcase
// endgenerate
`endif
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// PC
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
pc_f <= (`CFG_EBA_RESET-4)/4;
pc_d <= {`LM32_PC_WIDTH{1'b0}};
pc_x <= {`LM32_PC_WIDTH{1'b0}};
pc_m <= {`LM32_PC_WIDTH{1'b0}};
pc_w <= {`LM32_PC_WIDTH{1'b0}};
end
else
begin
if (stall_f == `FALSE)
pc_f <= pc_a;
if (stall_d == `FALSE)
pc_d <= pc_f;
if (stall_x == `FALSE)
pc_x <= pc_d;
if (stall_m == `FALSE)
pc_m <= pc_x;
pc_w <= pc_m;
end
end
`ifdef LM32_CACHE_ENABLED
// Address to restart from after a cache miss has been handled
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
restart_address <= {`LM32_PC_WIDTH{1'b0}};
else
begin
`ifdef CFG_DCACHE_ENABLED
`ifdef CFG_ICACHE_ENABLED
// D-cache restart address must take priority, otherwise instructions will be lost
if (dcache_refill_request == `TRUE)
restart_address <= pc_w;
else if ((icache_refill_request == `TRUE) && (!dcache_refilling))
restart_address <= icache_refill_address;
`else
if (dcache_refill_request == `TRUE)
restart_address <= pc_w;
`endif
`else
`ifdef CFG_ICACHE_ENABLED
if (icache_refill_request == `TRUE)
restart_address <= icache_refill_address;
`endif
`endif
end
end
`endif
// Record where instruction was fetched from
`ifdef CFG_IROM_ENABLED
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
irom_select_f <= `FALSE;
else
begin
if (stall_f == `FALSE)
irom_select_f <= irom_select_a;
end
end
`endif
`ifdef CFG_HW_DEBUG_ENABLED
assign jtag_access_complete = (i_cyc_o == `TRUE) && ((i_ack_i == `TRUE) || (i_err_i == `TRUE)) && (jtag_access == `TRUE);
always @*
begin
case (jtag_address[1:0])
2'b00: jtag_read_data = i_dat_i[`LM32_BYTE_3_RNG];
2'b01: jtag_read_data = i_dat_i[`LM32_BYTE_2_RNG];
2'b10: jtag_read_data = i_dat_i[`LM32_BYTE_1_RNG];
2'b11: jtag_read_data = i_dat_i[`LM32_BYTE_0_RNG];
endcase
end
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone interface
`ifdef CFG_ICACHE_ENABLED
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
i_cyc_o <= `FALSE;
i_stb_o <= `FALSE;
i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
i_cti_o <= `LM32_CTYPE_END;
i_lock_o <= `FALSE;
icache_refill_data <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
icache_refill_ready <= `FALSE;
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_f <= `FALSE;
`endif
`ifdef CFG_HW_DEBUG_ENABLED
i_we_o <= `FALSE;
i_sel_o <= 4'b1111;
jtag_access <= `FALSE;
`endif
end
else
begin
icache_refill_ready <= `FALSE;
// Is a cycle in progress?
if (i_cyc_o == `TRUE)
begin
// Has cycle completed?
if ((i_ack_i == `TRUE) || (i_err_i == `TRUE))
begin
`ifdef CFG_HW_DEBUG_ENABLED
if (jtag_access == `TRUE)
begin
i_cyc_o <= `FALSE;
i_stb_o <= `FALSE;
i_we_o <= `FALSE;
jtag_access <= `FALSE;
end
else
`endif
begin
if (last_word == `TRUE)
begin
// Cache line fill complete
i_cyc_o <= `FALSE;
i_stb_o <= `FALSE;
i_lock_o <= `FALSE;
end
// Fetch next word in cache line
i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
i_cti_o <= next_cycle_type;
// Write fetched data into instruction cache
icache_refill_ready <= `TRUE;
icache_refill_data <= i_dat_i;
end
end
`ifdef CFG_BUS_ERRORS_ENABLED
if (i_err_i == `TRUE)
begin
bus_error_f <= `TRUE;
$display ("Instruction bus error. Address: %x", i_adr_o);
end
`endif
end
else
begin
if ((icache_refill_request == `TRUE) && (icache_refill_ready == `FALSE))
begin
// Read first word of cache line
`ifdef CFG_HW_DEBUG_ENABLED
i_sel_o <= 4'b1111;
`endif
i_adr_o <= {first_address, 2'b00};
i_cyc_o <= `TRUE;
i_stb_o <= `TRUE;
i_cti_o <= first_cycle_type;
//i_lock_o <= `TRUE;
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_f <= `FALSE;
`endif
end
`ifdef CFG_HW_DEBUG_ENABLED
else
begin
if ((jtag_read_enable == `TRUE) || (jtag_write_enable == `TRUE))
begin
case (jtag_address[1:0])
2'b00: i_sel_o <= 4'b1000;
2'b01: i_sel_o <= 4'b0100;
2'b10: i_sel_o <= 4'b0010;
2'b11: i_sel_o <= 4'b0001;
endcase
i_adr_o <= jtag_address;
i_dat_o <= {4{jtag_write_data}};
i_cyc_o <= `TRUE;
i_stb_o <= `TRUE;
i_we_o <= jtag_write_enable;
i_cti_o <= `LM32_CTYPE_END;
jtag_access <= `TRUE;
end
end
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
// Clear bus error when exception taken, otherwise they would be
// continually generated if exception handler is cached
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
if (branch_taken_x == `TRUE)
bus_error_f <= `FALSE;
`endif
if (branch_taken_m == `TRUE)
bus_error_f <= `FALSE;
`endif
end
end
end
`else
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
i_cyc_o <= `FALSE;
i_stb_o <= `FALSE;
i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
i_cti_o <= `LM32_CTYPE_CLASSIC;
i_lock_o <= `FALSE;
wb_data_f <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_f <= `FALSE;
`endif
end
else
begin
// Is a cycle in progress?
if (i_cyc_o == `TRUE)
begin
// Has cycle completed?
if((i_ack_i == `TRUE) || (i_err_i == `TRUE))
begin
// Cycle complete
i_cyc_o <= `FALSE;
i_stb_o <= `FALSE;
// Register fetched instruction
wb_data_f <= i_dat_i;
end
`ifdef CFG_BUS_ERRORS_ENABLED
if (i_err_i == `TRUE)
begin
bus_error_f <= `TRUE;
$display ("Instruction bus error. Address: %x", i_adr_o);
end
`endif
end
else
begin
// Wait for an instruction fetch from an external address
if ( (stall_a == `FALSE)
`ifdef CFG_IROM_ENABLED
&& (irom_select_a == `FALSE)
`endif
)
begin
// Fetch instruction
`ifdef CFG_HW_DEBUG_ENABLED
i_sel_o <= 4'b1111;
`endif
i_adr_o <= {pc_a, 2'b00};
i_cyc_o <= `TRUE;
i_stb_o <= `TRUE;
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_f <= `FALSE;
`endif
end
end
end
end
`endif
`endif
// Instruction register
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
instruction_d <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_d <= `FALSE;
`endif
end
else
begin
if (stall_d == `FALSE)
begin
instruction_d <= instruction_f;
`ifdef CFG_BUS_ERRORS_ENABLED
bus_error_d <= bus_error_f;
`endif
end
end
end
endmodule

View File

@@ -0,0 +1,333 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_interrupt.v
// Title : Interrupt logic
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "system_conf.v"
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_interrupt (
// ----- Inputs -------
clk_i,
rst_i,
// From external devices
interrupt_n,
// From pipeline
stall_x,
`ifdef CFG_DEBUG_ENABLED
non_debug_exception,
debug_exception,
`else
exception,
`endif
eret_q_x,
`ifdef CFG_DEBUG_ENABLED
bret_q_x,
`endif
csr,
csr_write_data,
csr_write_enable,
// ----- Outputs -------
interrupt_exception,
// To pipeline
csr_read_data
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter interrupts = `CFG_INTERRUPTS; // Number of interrupts
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input [interrupts-1:0] interrupt_n; // Interrupt pins, active-low
input stall_x; // Stall X pipeline stage
`ifdef CFG_DEBUG_ENABLED
input non_debug_exception; // Non-debug related exception has been raised
input debug_exception; // Debug-related exception has been raised
`else
input exception; // Exception has been raised
`endif
input eret_q_x; // Return from exception
`ifdef CFG_DEBUG_ENABLED
input bret_q_x; // Return from breakpoint
`endif
input [`LM32_CSR_RNG] csr; // CSR read/write index
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
input csr_write_enable; // CSR write enable
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output interrupt_exception; // Request to raide an interrupt exception
wire interrupt_exception;
output [`LM32_WORD_RNG] csr_read_data; // Data read from CSR
reg [`LM32_WORD_RNG] csr_read_data;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire [interrupts-1:0] asserted; // Which interrupts are currently being asserted
wire [interrupts-1:0] interrupt_n_exception;
// Interrupt CSRs
reg ie; // Interrupt enable
reg eie; // Exception interrupt enable
`ifdef CFG_DEBUG_ENABLED
reg bie; // Breakpoint interrupt enable
`endif
reg [interrupts-1:0] ip; // Interrupt pending
reg [interrupts-1:0] im; // Interrupt mask
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Determine which interrupts have occured and are unmasked
assign interrupt_n_exception = ip & im;
// Determine if any unmasked interrupts have occured
assign interrupt_exception = (|interrupt_n_exception) & ie;
// Determine which interrupts are currently being asserted (active-low) or are already pending
assign asserted = ip | ~interrupt_n;
//assign ie_csr_read_data = {{`LM32_WORD_WIDTH-3{1'b0}},
//`ifdef CFG_DEBUG_ENABLED
// bie,
//`else
// 1'b0,
//`endif
// eie,
// ie
// };
wire ip_csr_read_data = ip;
wire im_csr_read_data = im;
// XXX JB XXX
// generate
// if (interrupts > 1)
// begin
// CSR read
always @*
begin
case (csr)
`LM32_CSR_IE: csr_read_data = {{`LM32_WORD_WIDTH-3{1'b0}},
`ifdef CFG_DEBUG_ENABLED
bie,
`else
1'b0,
`endif
eie,
ie
};
`LM32_CSR_IP: csr_read_data = ip;
`LM32_CSR_IM: csr_read_data = im;
default: csr_read_data = {`LM32_WORD_WIDTH{1'bx}};
endcase
end
// XXX JB XXX
// end
// else
// begin
//// CSR read
//always @*
//begin
// case (csr)
// `LM32_CSR_IE: csr_read_data = {{`LM32_WORD_WIDTH-3{1'b0}},
//`ifdef CFG_DEBUG_ENABLED
// bie,
//`else
// 1'b0,
//`endif
// eie,
// ie
// };
// `LM32_CSR_IP: csr_read_data = ip;
// default: csr_read_data = {`LM32_WORD_WIDTH{1'bx}};
// endcase
//end
// end
//endgenerate
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// XXX JB XXX
//generate
// if (interrupts > 1)
// begin
// IE, IM, IP - Interrupt Enable, Interrupt Mask and Interrupt Pending CSRs
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
ie <= `FALSE;
eie <= `FALSE;
`ifdef CFG_DEBUG_ENABLED
bie <= `FALSE;
`endif
im <= {interrupts{1'b0}};
ip <= {interrupts{1'b0}};
end
else
begin
// Set IP bit when interrupt line is asserted
ip <= asserted;
`ifdef CFG_DEBUG_ENABLED
if (non_debug_exception == `TRUE)
begin
// Save and then clear interrupt enable
eie <= ie;
ie <= `FALSE;
end
else if (debug_exception == `TRUE)
begin
// Save and then clear interrupt enable
bie <= ie;
ie <= `FALSE;
end
`else
if (exception == `TRUE)
begin
// Save and then clear interrupt enable
eie <= ie;
ie <= `FALSE;
end
`endif
else if (stall_x == `FALSE)
begin
if (eret_q_x == `TRUE)
// Restore interrupt enable
ie <= eie;
`ifdef CFG_DEBUG_ENABLED
else if (bret_q_x == `TRUE)
// Restore interrupt enable
ie <= bie;
`endif
else if (csr_write_enable == `TRUE)
begin
// Handle wcsr write
if (csr == `LM32_CSR_IE)
begin
ie <= csr_write_data[0];
eie <= csr_write_data[1];
`ifdef CFG_DEBUG_ENABLED
bie <= csr_write_data[2];
`endif
end
if (csr == `LM32_CSR_IM)
im <= csr_write_data[interrupts-1:0];
if (csr == `LM32_CSR_IP)
ip <= asserted & ~csr_write_data[interrupts-1:0];
end
end
end
end
// end
//else
// begin
//// IE, IM, IP - Interrupt Enable, Interrupt Mask and Interrupt Pending CSRs
//always @(posedge clk_i `CFG_RESET_SENSITIVITY)
//begin
// if (rst_i == `TRUE)
// begin
// ie <= `FALSE;
// eie <= `FALSE;
//`ifdef CFG_DEBUG_ENABLED
// bie <= `FALSE;
//`endif
// ip <= {interrupts{1'b0}};
// end
// else
// begin
// // Set IP bit when interrupt line is asserted
// ip <= asserted;
//`ifdef CFG_DEBUG_ENABLED
// if (non_debug_exception == `TRUE)
// begin
// // Save and then clear interrupt enable
// eie <= ie;
// ie <= `FALSE;
// end
// else if (debug_exception == `TRUE)
// begin
// // Save and then clear interrupt enable
// bie <= ie;
// ie <= `FALSE;
// end
//`else
// if (exception == `TRUE)
// begin
// // Save and then clear interrupt enable
// eie <= ie;
// ie <= `FALSE;
// end
//`endif
// else if (stall_x == `FALSE)
// begin
// if (eret_q_x == `TRUE)
// // Restore interrupt enable
// ie <= eie;
//`ifdef CFG_DEBUG_ENABLED
// else if (bret_q_x == `TRUE)
// // Restore interrupt enable
// ie <= bie;
//`endif
// else if (csr_write_enable == `TRUE)
// begin
// // Handle wcsr write
// if (csr == `LM32_CSR_IE)
// begin
// ie <= csr_write_data[0];
// eie <= csr_write_data[1];
//`ifdef CFG_DEBUG_ENABLED
// bie <= csr_write_data[2];
//`endif
// end
// if (csr == `LM32_CSR_IP)
// ip <= asserted & ~csr_write_data[interrupts-1:0];
// end
// end
// end
//end
// end
//endgenerate
endmodule

View File

@@ -0,0 +1,491 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_jtag.v
// Title : JTAG interface
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
`ifdef CFG_JTAG_ENABLED
`define LM32_DP 3'b000
`define LM32_TX 3'b001
`define LM32_RX 3'b010
// LM32 Debug Protocol commands IDs
`define LM32_DP_RNG 3:0
`define LM32_DP_READ_MEMORY 4'b0001
`define LM32_DP_WRITE_MEMORY 4'b0010
`define LM32_DP_READ_SEQUENTIAL 4'b0011
`define LM32_DP_WRITE_SEQUENTIAL 4'b0100
`define LM32_DP_WRITE_CSR 4'b0101
`define LM32_DP_BREAK 4'b0110
`define LM32_DP_RESET 4'b0111
// States for FSM
`define LM32_JTAG_STATE_RNG 3:0
`define LM32_JTAG_STATE_READ_COMMAND 4'h0
`define LM32_JTAG_STATE_READ_BYTE_0 4'h1
`define LM32_JTAG_STATE_READ_BYTE_1 4'h2
`define LM32_JTAG_STATE_READ_BYTE_2 4'h3
`define LM32_JTAG_STATE_READ_BYTE_3 4'h4
`define LM32_JTAG_STATE_READ_BYTE_4 4'h5
`define LM32_JTAG_STATE_PROCESS_COMMAND 4'h6
`define LM32_JTAG_STATE_WAIT_FOR_MEMORY 4'h7
`define LM32_JTAG_STATE_WAIT_FOR_CSR 4'h8
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_jtag (
// ----- Inputs -------
clk_i,
rst_i,
jtag_clk,
jtag_update,
jtag_reg_q,
jtag_reg_addr_q,
`ifdef CFG_JTAG_UART_ENABLED
csr,
csr_write_enable,
csr_write_data,
stall_x,
`endif
`ifdef CFG_HW_DEBUG_ENABLED
jtag_read_data,
jtag_access_complete,
`endif
`ifdef CFG_DEBUG_ENABLED
exception_q_w,
`endif
// ----- Outputs -------
`ifdef CFG_JTAG_UART_ENABLED
jtx_csr_read_data,
jrx_csr_read_data,
`endif
`ifdef CFG_HW_DEBUG_ENABLED
jtag_csr_write_enable,
jtag_csr_write_data,
jtag_csr,
jtag_read_enable,
jtag_write_enable,
jtag_write_data,
jtag_address,
`endif
`ifdef CFG_DEBUG_ENABLED
jtag_break,
jtag_reset,
`endif
jtag_reg_d,
jtag_reg_addr_d
);
parameter lat_family = `LATTICE_FAMILY;
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input jtag_clk; // JTAG clock
input jtag_update; // JTAG data register has been updated
input [`LM32_BYTE_RNG] jtag_reg_q; // JTAG data register
input [2:0] jtag_reg_addr_q; // JTAG data register
`ifdef CFG_JTAG_UART_ENABLED
input [`LM32_CSR_RNG] csr; // CSR to write
input csr_write_enable; // CSR write enable
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
input stall_x; // Stall instruction in X stage
`endif
`ifdef CFG_HW_DEBUG_ENABLED
input [`LM32_BYTE_RNG] jtag_read_data; // Data read from requested address
input jtag_access_complete; // Memory access if complete
`endif
`ifdef CFG_DEBUG_ENABLED
input exception_q_w; // Indicates an exception has occured in W stage
`endif
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
`ifdef CFG_JTAG_UART_ENABLED
output [`LM32_WORD_RNG] jtx_csr_read_data; // Value of JTX CSR for rcsr instructions
wire [`LM32_WORD_RNG] jtx_csr_read_data;
output [`LM32_WORD_RNG] jrx_csr_read_data; // Value of JRX CSR for rcsr instructions
wire [`LM32_WORD_RNG] jrx_csr_read_data;
`endif
`ifdef CFG_HW_DEBUG_ENABLED
output jtag_csr_write_enable; // CSR write enable
reg jtag_csr_write_enable;
output [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to specified CSR
wire [`LM32_WORD_RNG] jtag_csr_write_data;
output [`LM32_CSR_RNG] jtag_csr; // CSR to write
wire [`LM32_CSR_RNG] jtag_csr;
output jtag_read_enable; // Memory read enable
reg jtag_read_enable;
output jtag_write_enable; // Memory write enable
reg jtag_write_enable;
output [`LM32_BYTE_RNG] jtag_write_data; // Data to write to specified address
wire [`LM32_BYTE_RNG] jtag_write_data;
output [`LM32_WORD_RNG] jtag_address; // Memory read/write address
wire [`LM32_WORD_RNG] jtag_address;
`endif
`ifdef CFG_DEBUG_ENABLED
output jtag_break; // Request to raise a breakpoint exception
reg jtag_break;
output jtag_reset; // Request to raise a reset exception
reg jtag_reset;
`endif
output [`LM32_BYTE_RNG] jtag_reg_d;
reg [`LM32_BYTE_RNG] jtag_reg_d;
output [2:0] jtag_reg_addr_d;
wire [2:0] jtag_reg_addr_d;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg rx_toggle; // Clock-domain crossing registers
reg rx_toggle_r; // Registered version of rx_toggle
reg rx_toggle_r_r; // Registered version of rx_toggle_r
reg rx_toggle_r_r_r; // Registered version of rx_toggle_r_r
reg [`LM32_BYTE_RNG] rx_byte;
reg [2:0] rx_addr;
`ifdef CFG_JTAG_UART_ENABLED
reg [`LM32_BYTE_RNG] uart_tx_byte; // UART TX data
reg uart_tx_valid; // TX data is valid
reg [`LM32_BYTE_RNG] uart_rx_byte; // UART RX data
reg uart_rx_valid; // RX data is valid
`endif
reg [`LM32_DP_RNG] command; // The last received command
`ifdef CFG_HW_DEBUG_ENABLED
reg [`LM32_BYTE_RNG] jtag_byte_0; // Registers to hold command paramaters
reg [`LM32_BYTE_RNG] jtag_byte_1;
reg [`LM32_BYTE_RNG] jtag_byte_2;
reg [`LM32_BYTE_RNG] jtag_byte_3;
reg [`LM32_BYTE_RNG] jtag_byte_4;
reg processing; // Indicates if we're still processing a memory read/write
`endif
reg [`LM32_JTAG_STATE_RNG] state; // Current state of FSM
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
`ifdef CFG_HW_DEBUG_ENABLED
assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3};
assign jtag_csr = jtag_byte_4[`LM32_CSR_RNG];
assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3};
assign jtag_write_data = jtag_byte_4;
`endif
// Generate status flags for reading via the JTAG interface
`ifdef CFG_JTAG_UART_ENABLED
assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid};
`else
assign jtag_reg_addr_d[1:0] = 2'b00;
`endif
`ifdef CFG_HW_DEBUG_ENABLED
assign jtag_reg_addr_d[2] = processing;
`else
assign jtag_reg_addr_d[2] = 1'b0;
`endif
`ifdef CFG_JTAG_UART_ENABLED
assign jtx_csr_read_data = {{`LM32_WORD_WIDTH-9{1'b0}}, uart_tx_valid, 8'h00};
assign jrx_csr_read_data = {{`LM32_WORD_WIDTH-9{1'b0}}, uart_rx_valid, uart_rx_byte};
`endif
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// Toggle a flag when a JTAG write occurs
generate
if (lat_family == "EC" || lat_family == "ECP" ||
lat_family == "XP" || lat_family == "ECP2" || lat_family == "ECP2M") begin
always @(posedge jtag_clk `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
rx_toggle <= 1'b0;
else
if (jtag_update == `TRUE)
rx_toggle <= ~rx_toggle;
end
end else begin // for SC & SCM
always @(negedge jtag_update `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
rx_toggle <= 1'b0;
else
rx_toggle <= ~rx_toggle;
end
end
endgenerate
always @(*)
begin
rx_byte = jtag_reg_q;
rx_addr = jtag_reg_addr_q;
end
// Clock domain crossing from JTAG clock domain to CPU clock domain
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
rx_toggle_r <= 1'b0;
rx_toggle_r_r <= 1'b0;
rx_toggle_r_r_r <= 1'b0;
end
else
begin
rx_toggle_r <= rx_toggle;
rx_toggle_r_r <= rx_toggle_r;
rx_toggle_r_r_r <= rx_toggle_r_r;
end
end
// LM32 debug protocol state machine
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
state <= `LM32_JTAG_STATE_READ_COMMAND;
command <= 4'b0000;
jtag_reg_d <= 8'h00;
`ifdef CFG_HW_DEBUG_ENABLED
processing <= `FALSE;
jtag_csr_write_enable <= `FALSE;
jtag_read_enable <= `FALSE;
jtag_write_enable <= `FALSE;
`endif
`ifdef CFG_DEBUG_ENABLED
jtag_break <= `FALSE;
jtag_reset <= `FALSE;
`endif
`ifdef CFG_JTAG_UART_ENABLED
uart_tx_byte <= 8'h00;
uart_tx_valid <= `FALSE;
uart_rx_byte <= 8'h00;
uart_rx_valid <= `FALSE;
`endif
end
else
begin
`ifdef CFG_JTAG_UART_ENABLED
if ((csr_write_enable == `TRUE) && (stall_x == `FALSE))
begin
case (csr)
`LM32_CSR_JTX:
begin
// Set flag indicating data is available
uart_tx_byte <= csr_write_data[`LM32_BYTE_0_RNG];
uart_tx_valid <= `TRUE;
end
`LM32_CSR_JRX:
begin
// Clear flag indidicating data has been received
uart_rx_valid <= `FALSE;
end
endcase
end
`endif
`ifdef CFG_DEBUG_ENABLED
// When an exception has occured, clear the requests
if (exception_q_w == `TRUE)
begin
jtag_break <= `FALSE;
jtag_reset <= `FALSE;
end
`endif
case (state)
`LM32_JTAG_STATE_READ_COMMAND:
begin
// Wait for rx register to toggle which indicates new data is available
if (rx_toggle_r_r != rx_toggle_r_r_r)
begin
command <= rx_byte[7:4];
case (rx_addr)
`ifdef CFG_DEBUG_ENABLED
`LM32_DP:
begin
case (rx_byte[7:4])
`ifdef CFG_HW_DEBUG_ENABLED
`LM32_DP_READ_MEMORY:
state <= `LM32_JTAG_STATE_READ_BYTE_0;
`LM32_DP_READ_SEQUENTIAL:
begin
{jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1;
state <= `LM32_JTAG_STATE_PROCESS_COMMAND;
end
`LM32_DP_WRITE_MEMORY:
state <= `LM32_JTAG_STATE_READ_BYTE_0;
`LM32_DP_WRITE_SEQUENTIAL:
begin
{jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1;
state <= 5;
end
`LM32_DP_WRITE_CSR:
state <= `LM32_JTAG_STATE_READ_BYTE_0;
`endif
`LM32_DP_BREAK:
begin
`ifdef CFG_JTAG_UART_ENABLED
uart_rx_valid <= `FALSE;
uart_tx_valid <= `FALSE;
`endif
jtag_break <= `TRUE;
end
`LM32_DP_RESET:
begin
`ifdef CFG_JTAG_UART_ENABLED
uart_rx_valid <= `FALSE;
uart_tx_valid <= `FALSE;
`endif
jtag_reset <= `TRUE;
end
endcase
end
`endif
`ifdef CFG_JTAG_UART_ENABLED
`LM32_TX:
begin
uart_rx_byte <= rx_byte;
uart_rx_valid <= `TRUE;
end
`LM32_RX:
begin
jtag_reg_d <= uart_tx_byte;
uart_tx_valid <= `FALSE;
end
`endif
default:
;
endcase
end
end
`ifdef CFG_HW_DEBUG_ENABLED
`LM32_JTAG_STATE_READ_BYTE_0:
begin
if (rx_toggle_r_r != rx_toggle_r_r_r)
begin
jtag_byte_0 <= rx_byte;
state <= `LM32_JTAG_STATE_READ_BYTE_1;
end
end
`LM32_JTAG_STATE_READ_BYTE_1:
begin
if (rx_toggle_r_r != rx_toggle_r_r_r)
begin
jtag_byte_1 <= rx_byte;
state <= `LM32_JTAG_STATE_READ_BYTE_2;
end
end
`LM32_JTAG_STATE_READ_BYTE_2:
begin
if (rx_toggle_r_r != rx_toggle_r_r_r)
begin
jtag_byte_2 <= rx_byte;
state <= `LM32_JTAG_STATE_READ_BYTE_3;
end
end
`LM32_JTAG_STATE_READ_BYTE_3:
begin
if (rx_toggle_r_r != rx_toggle_r_r_r)
begin
jtag_byte_3 <= rx_byte;
if (command == `LM32_DP_READ_MEMORY)
state <= `LM32_JTAG_STATE_PROCESS_COMMAND;
else
state <= `LM32_JTAG_STATE_READ_BYTE_4;
end
end
`LM32_JTAG_STATE_READ_BYTE_4:
begin
if (rx_toggle_r_r != rx_toggle_r_r_r)
begin
jtag_byte_4 <= rx_byte;
state <= `LM32_JTAG_STATE_PROCESS_COMMAND;
end
end
`LM32_JTAG_STATE_PROCESS_COMMAND:
begin
case (command)
`LM32_DP_READ_MEMORY,
`LM32_DP_READ_SEQUENTIAL:
begin
jtag_read_enable <= `TRUE;
processing <= `TRUE;
state <= `LM32_JTAG_STATE_WAIT_FOR_MEMORY;
end
`LM32_DP_WRITE_MEMORY,
`LM32_DP_WRITE_SEQUENTIAL:
begin
jtag_write_enable <= `TRUE;
processing <= `TRUE;
state <= `LM32_JTAG_STATE_WAIT_FOR_MEMORY;
end
`LM32_DP_WRITE_CSR:
begin
jtag_csr_write_enable <= `TRUE;
processing <= `TRUE;
state <= `LM32_JTAG_STATE_WAIT_FOR_CSR;
end
endcase
end
`LM32_JTAG_STATE_WAIT_FOR_MEMORY:
begin
if (jtag_access_complete == `TRUE)
begin
jtag_read_enable <= `FALSE;
jtag_reg_d <= jtag_read_data;
jtag_write_enable <= `FALSE;
processing <= `FALSE;
state <= `LM32_JTAG_STATE_READ_COMMAND;
end
end
`LM32_JTAG_STATE_WAIT_FOR_CSR:
begin
jtag_csr_write_enable <= `FALSE;
processing <= `FALSE;
state <= `LM32_JTAG_STATE_READ_COMMAND;
end
`endif
endcase
end
end
endmodule
`endif

View File

@@ -0,0 +1,588 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_load_store_unit.v
// Title : Load and store unit
// Dependencies : lm32_include.v
// Version : 6.0.13
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_load_store_unit (
// ----- Inputs -------
clk_i,
rst_i,
// From pipeline
stall_a,
stall_x,
stall_m,
kill_x,
kill_m,
exception_m,
store_operand_x,
load_store_address_x,
load_store_address_m,
load_store_address_w,
load_q_x,
load_q_m,
store_q_m,
sign_extend_x,
size_x,
`ifdef CFG_DCACHE_ENABLED
dflush,
`endif
// From Wishbone
d_dat_i,
d_ack_i,
d_err_i,
d_rty_i,
// ----- Outputs -------
// To pipeline
`ifdef CFG_DCACHE_ENABLED
dcache_refill_request,
dcache_restart_request,
dcache_stall_request,
dcache_refilling,
`endif
load_data_w,
stall_wb_load,
// To Wishbone
d_dat_o,
d_adr_o,
d_cyc_o,
d_sel_o,
d_stb_o,
d_we_o,
d_cti_o,
d_lock_o,
d_bte_o
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter associativity = 1; // Associativity of the cache (Number of ways)
parameter sets = 512; // Number of sets
parameter bytes_per_line = 16; // Number of bytes per cache line
parameter base_address = 0; // Base address of cachable memory
parameter limit = 0; // Limit (highest address) of cachable memory
// For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
//localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2;
localparam addr_offset_width = 2;
localparam addr_offset_lsb = 2;
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_a; // A stage stall
input stall_x; // X stage stall
input stall_m; // M stage stall
input kill_x; // Kill instruction in X stage
input kill_m; // Kill instruction in M stage
input exception_m; // An exception occured in the M stage
input [`LM32_WORD_RNG] store_operand_x; // Data read from register to store
input [`LM32_WORD_RNG] load_store_address_x; // X stage load/store address
input [`LM32_WORD_RNG] load_store_address_m; // M stage load/store address
input [1:0] load_store_address_w; // W stage load/store address (only least two significant bits are needed)
input load_q_x; // Load instruction in X stage
input load_q_m; // Load instruction in M stage
input store_q_m; // Store instruction in M stage
input sign_extend_x; // Whether load instruction in X stage should sign extend or zero extend
input [`LM32_SIZE_RNG] size_x; // Size of load or store (byte, hword, word)
`ifdef CFG_DCACHE_ENABLED
input dflush; // Flush the data cache
`endif
input [`LM32_WORD_RNG] d_dat_i; // Data Wishbone interface read data
input d_ack_i; // Data Wishbone interface acknowledgement
input d_err_i; // Data Wishbone interface error
input d_rty_i; // Data Wishbone interface retry
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
`ifdef CFG_DCACHE_ENABLED
output dcache_refill_request; // Request to refill data cache
wire dcache_refill_request;
output dcache_restart_request; // Request to restart the instruction that caused a data cache miss
wire dcache_restart_request;
output dcache_stall_request; // Data cache stall request
wire dcache_stall_request;
output dcache_refilling;
wire dcache_refilling;
`endif
output [`LM32_WORD_RNG] load_data_w; // Result of a load instruction
reg [`LM32_WORD_RNG] load_data_w;
output stall_wb_load; // Request to stall pipeline due to a load from the Wishbone interface
reg stall_wb_load;
output [`LM32_WORD_RNG] d_dat_o; // Data Wishbone interface write data
reg [`LM32_WORD_RNG] d_dat_o;
output [`LM32_WORD_RNG] d_adr_o; // Data Wishbone interface address
reg [`LM32_WORD_RNG] d_adr_o;
output d_cyc_o; // Data Wishbone interface cycle
reg d_cyc_o;
output [`LM32_BYTE_SELECT_RNG] d_sel_o; // Data Wishbone interface byte select
reg [`LM32_BYTE_SELECT_RNG] d_sel_o;
output d_stb_o; // Data Wishbone interface strobe
reg d_stb_o;
output d_we_o; // Data Wishbone interface write enable
reg d_we_o;
output [`LM32_CTYPE_RNG] d_cti_o; // Data Wishbone interface cycle type
wire [`LM32_CTYPE_RNG] d_cti_o;
output d_lock_o; // Date Wishbone interface lock bus
wire d_lock_o;
output [`LM32_BTYPE_RNG] d_bte_o; // Data Wishbone interface burst type
wire [`LM32_BTYPE_RNG] d_bte_o;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
// Microcode pipeline registers - See inputs for description
reg [`LM32_SIZE_RNG] size_m;
reg [`LM32_SIZE_RNG] size_w;
reg sign_extend_m;
reg sign_extend_w;
reg [`LM32_WORD_RNG] store_data_x;
reg [`LM32_WORD_RNG] store_data_m;
reg [`LM32_BYTE_SELECT_RNG] byte_enable_x;
reg [`LM32_BYTE_SELECT_RNG] byte_enable_m;
wire [`LM32_WORD_RNG] data_m;
reg [`LM32_WORD_RNG] data_w;
`ifdef CFG_DCACHE_ENABLED
wire dcache_select_x; // Select data cache to load from / store to
reg dcache_select_m;
wire [`LM32_WORD_RNG] dcache_data_m; // Data read from cache
wire [`LM32_WORD_RNG] dcache_refill_address; // Address to refill data cache from
reg dcache_refill_ready; // Indicates the next word of refill data is ready
wire last_word; // Indicates if this is the last word in the cache line
wire [`LM32_WORD_RNG] first_address; // First cache refill address
`endif
`ifdef CFG_DRAM_ENABLED
wire dram_select_x; // Select data RAM to load from / store to
reg dram_select_m;
wire [`LM32_WORD_RNG] dram_data_m; // Data read from data RAM
wire [`LM32_WORD_RNG] dram_store_data_m; // Data to write to RAM
`endif
wire wb_select_x; // Select Wishbone to load from / store to
reg wb_select_m;
reg [`LM32_WORD_RNG] wb_data_m; // Data read from Wishbone
reg wb_load_complete; // Indicates when a Wishbone load is complete
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
`ifdef CFG_DRAM_ENABLED
// Data RAM
pmi_ram_dp_true #(
// ----- Parameters -------
.pmi_addr_depth_a (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
.pmi_addr_width_a ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
.pmi_data_width_a (`LM32_WORD_WIDTH),
.pmi_addr_depth_b (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
.pmi_addr_width_b ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
.pmi_data_width_b (`LM32_WORD_WIDTH),
.pmi_regmode_a ("noreg"),
.pmi_regmode_b ("noreg"),
.pmi_gsr ("enable"),
.pmi_resetmode ("async"),
.pmi_init_file (`CFG_DRAM_INIT_FILE),
.pmi_init_file_format ("hex"),
.module_type ("pmi_ram_dp")
) ram (
// ----- Inputs -------
.ClockA (clk_i),
.ClockB (clk_i),
.ResetA (rst_i),
.ResetB (rst_i),
.DataInA ({32{1'b0}}),
.DataInB (dram_store_data_m),
.AddressA (load_store_address_x[(clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)+2-1:2]),
.AddressB (load_store_address_m[(clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)+2-1:2]),
.ClockEnA (!stall_x),
.ClockEnB (!stall_m),
.WrA (`FALSE),
.WrB (store_q_m),
// ----- Outputs -------
.QA (dram_data_m),
.QB ()
);
`endif
`ifdef CFG_DCACHE_ENABLED
// Data cache
lm32_dcache #(
.associativity (associativity),
.sets (sets),
.bytes_per_line (bytes_per_line),
.base_address (base_address),
.limit (limit)
) dcache (
// ----- Inputs -----
.clk_i (clk_i),
.rst_i (rst_i),
.stall_a (stall_a),
.stall_x (stall_x),
.stall_m (stall_m),
.address_x (load_store_address_x),
.address_m (load_store_address_m),
.load_q_m (load_q_m & dcache_select_m),
.store_q_m (store_q_m),
.store_data (store_data_m),
.store_byte_select (byte_enable_m),
.refill_ready (dcache_refill_ready),
.refill_data (wb_data_m),
.dflush (dflush),
// ----- Outputs -----
.stall_request (dcache_stall_request),
.restart_request (dcache_restart_request),
.refill_request (dcache_refill_request),
.refill_address (dcache_refill_address),
.refilling (dcache_refilling),
.load_data (dcache_data_m)
);
`endif
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Select where data should be loaded from / stored to
`ifdef CFG_DCACHE_ENABLED
assign dcache_select_x = (load_store_address_x >= `CFG_DCACHE_BASE_ADDRESS) && (load_store_address_x <= `CFG_DCACHE_LIMIT);
//assign dcache_select_x = (load_store_address_x >= `CFG_DCACHE_BASE_ADDRESS) && ~|load_store_address_x[`LM32_WORD_WIDTH-1:clogb2(`CFG_DCACHE_LIMIT-`CFG_DCACHE_BASE_ADDRESS)-1];
`endif
`ifdef CFG_DRAM_ENABLED
assign dram_select_x = (load_store_address_x >= `CFG_DRAM_BASE_ADDRESS) && (load_store_address_x <= `CFG_DRAM_LIMIT);
`endif
assign wb_select_x = `TRUE
`ifdef CFG_DCACHE_ENABLED
&& !dcache_select_x
`endif
`ifdef CFG_DRAM_ENABLED
&& !dram_select_x
`endif
;
// Make sure data to store is in correct byte lane
always @(*)
begin
case (size_x)
`LM32_SIZE_BYTE: store_data_x = {4{store_operand_x[7:0]}};
`LM32_SIZE_HWORD: store_data_x = {2{store_operand_x[15:0]}};
`LM32_SIZE_WORD: store_data_x = store_operand_x;
default: store_data_x = {`LM32_WORD_WIDTH{1'bx}};
endcase
end
// Generate byte enable accoring to size of load or store and address being accessed
always @(*)
begin
casez ({size_x, load_store_address_x[1:0]})
{`LM32_SIZE_BYTE, 2'b11}: byte_enable_x = 4'b0001;
{`LM32_SIZE_BYTE, 2'b10}: byte_enable_x = 4'b0010;
{`LM32_SIZE_BYTE, 2'b01}: byte_enable_x = 4'b0100;
{`LM32_SIZE_BYTE, 2'b00}: byte_enable_x = 4'b1000;
{`LM32_SIZE_HWORD, 2'b1?}: byte_enable_x = 4'b0011;
{`LM32_SIZE_HWORD, 2'b0?}: byte_enable_x = 4'b1100;
{`LM32_SIZE_WORD, 2'b??}: byte_enable_x = 4'b1111;
default: byte_enable_x = 4'bxxxx;
endcase
end
`ifdef CFG_DRAM_ENABLED
// Only replace selected bytes
assign dram_store_data_m[`LM32_BYTE_0_RNG] = byte_enable_m[0] ? store_data_m[`LM32_BYTE_0_RNG] : dram_data_m[`LM32_BYTE_0_RNG];
assign dram_store_data_m[`LM32_BYTE_1_RNG] = byte_enable_m[1] ? store_data_m[`LM32_BYTE_1_RNG] : dram_data_m[`LM32_BYTE_1_RNG];
assign dram_store_data_m[`LM32_BYTE_2_RNG] = byte_enable_m[2] ? store_data_m[`LM32_BYTE_2_RNG] : dram_data_m[`LM32_BYTE_2_RNG];
assign dram_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM32_BYTE_3_RNG] : dram_data_m[`LM32_BYTE_3_RNG];
`endif
// Select data from selected source
`ifdef CFG_DCACHE_ENABLED
`ifdef CFG_DRAM_ENABLED
assign data_m = wb_select_m == `TRUE
? wb_data_m
: dram_select_m == `TRUE
? dram_data_m
: dcache_data_m;
`else
assign data_m = wb_select_m == `TRUE ? wb_data_m : dcache_data_m;
`endif
`else
`ifdef CFG_DRAM_ENABLED
assign data_m = wb_select_m == `TRUE ? wb_data_m : dram_data_m;
`else
assign data_m = wb_data_m;
`endif
`endif
// Sub-word selection and sign/zero-extension for loads
always @(*)
begin
casez ({size_w, load_store_address_w[1:0]})
{`LM32_SIZE_BYTE, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]};
{`LM32_SIZE_BYTE, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]};
{`LM32_SIZE_BYTE, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]};
{`LM32_SIZE_BYTE, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]};
{`LM32_SIZE_HWORD, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]};
{`LM32_SIZE_HWORD, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]};
{`LM32_SIZE_WORD, 2'b??}: load_data_w = data_w;
default: load_data_w = {`LM32_WORD_WIDTH{1'bx}};
endcase
end
// Unused Wishbone signals
assign d_cti_o = `LM32_CTYPE_WIDTH'd0;
assign d_lock_o = `FALSE;
assign d_bte_o = `LM32_BTYPE_WIDTH'd0;
`ifdef CFG_DCACHE_ENABLED
// Generate signal to indicate last word in cache line
generate
if (bytes_per_line > 4)
begin
assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00};
assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1;
end
else
begin
assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:2], 2'b00};
assign last_word = `TRUE;
end
endgenerate
`endif
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// Data Wishbone interface
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
d_cyc_o <= `FALSE;
d_stb_o <= `FALSE;
d_dat_o <= {`LM32_WORD_WIDTH{1'b0}};
d_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
d_sel_o <= {`LM32_BYTE_SELECT_WIDTH{`FALSE}};
d_we_o <= `FALSE;
wb_data_m <= {`LM32_WORD_WIDTH{1'b0}};
wb_load_complete <= `FALSE;
stall_wb_load <= `FALSE;
`ifdef CFG_DCACHE_ENABLED
dcache_refill_ready <= `FALSE;
`endif
end
else
begin
`ifdef CFG_DCACHE_ENABLED
// Refill ready should only be asserted for a single cycle
dcache_refill_ready <= `FALSE;
`endif
// Is a Wishbone cycle already in progress?
if (d_cyc_o == `TRUE)
begin
// Is the cycle complete?
if ((d_ack_i == `TRUE) || (d_err_i == `TRUE))
begin
`ifdef CFG_DCACHE_ENABLED
if ((dcache_refilling == `TRUE) && (!last_word))
begin
// Fetch next word of cache line
d_adr_o[addr_offset_msb:addr_offset_lsb] <= d_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
end
else
`endif
begin
// Refill/access complete
d_cyc_o <= `FALSE;
d_stb_o <= `FALSE;
end
`ifdef CFG_DCACHE_ENABLED
// If we are performing a refill, indicate to cache next word of data is ready
dcache_refill_ready <= dcache_refilling;
`endif
// Register data read from Wishbone interface
wb_data_m <= d_dat_i;
// Don't set when stores complete - otherwise we'll deadlock if load in m stage
wb_load_complete <= !d_we_o;
end
// synthesis translate_off
if (d_err_i == `TRUE)
$display ("Data bus error. Address: %x", d_adr_o);
// synthesis translate_on
end
else
begin
`ifdef CFG_DCACHE_ENABLED
if (dcache_refill_request == `TRUE)
begin
// Start cache refill
d_adr_o <= first_address;
d_cyc_o <= `TRUE;
d_sel_o <= {`LM32_WORD_WIDTH/8{`TRUE}};
d_stb_o <= `TRUE;
d_we_o <= `FALSE;
end
else
`endif
if ( (store_q_m == `TRUE)
&& (stall_m == `FALSE)
`ifdef CFG_DRAM_ENABLED
&& !dram_select_m
`endif
)
begin
// Data cache is write through, so all stores go to memory
d_dat_o <= store_data_m;
d_adr_o <= load_store_address_m;
d_cyc_o <= `TRUE;
d_sel_o <= byte_enable_m;
d_stb_o <= `TRUE;
d_we_o <= `TRUE;
end
else if ( (load_q_m == `TRUE)
&& (wb_select_m == `TRUE)
&& (wb_load_complete == `FALSE)
/* stall_m will be TRUE, because stall_wb_load will be TRUE */
)
begin
// Read requested address
stall_wb_load <= `FALSE;
d_adr_o <= load_store_address_m;
d_cyc_o <= `TRUE;
d_sel_o <= byte_enable_m;
d_stb_o <= `TRUE;
d_we_o <= `FALSE;
end
end
// Clear load/store complete flag when instruction leaves M stage
if (stall_m == `FALSE)
wb_load_complete <= `FALSE;
// When a Wishbone load first enters the M stage, we need to stall it
if ((load_q_x == `TRUE) && (wb_select_x == `TRUE) && (stall_x == `FALSE))
stall_wb_load <= `TRUE;
// Clear stall request if load instruction is killed
if ((kill_m == `TRUE) || (exception_m == `TRUE))
stall_wb_load <= `FALSE;
end
end
// Pipeline registers
// X/M stage pipeline registers
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
sign_extend_m <= `FALSE;
size_m <= 2'b00;
byte_enable_m <= `FALSE;
store_data_m <= {`LM32_WORD_WIDTH{1'b0}};
`ifdef CFG_DCACHE_ENABLED
dcache_select_m <= `FALSE;
`endif
`ifdef CFG_DRAM_ENABLED
dram_select_m <= `FALSE;
`endif
wb_select_m <= `FALSE;
end
else
begin
if (stall_m == `FALSE)
begin
sign_extend_m <= sign_extend_x;
size_m <= size_x;
byte_enable_m <= byte_enable_x;
store_data_m <= store_data_x;
`ifdef CFG_DCACHE_ENABLED
dcache_select_m <= dcache_select_x;
`endif
`ifdef CFG_DRAM_ENABLED
dram_select_m <= dram_select_x;
`endif
wb_select_m <= wb_select_x;
end
end
end
// M/W stage pipeline registers
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
size_w <= 2'b00;
data_w <= {`LM32_WORD_WIDTH{1'b0}};
sign_extend_w <= `FALSE;
end
else
begin
size_w <= size_m;
data_w <= data_m;
sign_extend_w <= sign_extend_m;
end
end
/////////////////////////////////////////////////////
// Behavioural Logic
/////////////////////////////////////////////////////
// synthesis translate_off
// Check for non-aligned loads or stores
always @(posedge clk_i)
begin
if (((load_q_m == `TRUE) || (store_q_m == `TRUE)) && (stall_m == `FALSE))
begin
if ((size_m === `LM32_SIZE_HWORD) && (load_store_address_m[0] !== 1'b0))
$display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time);
if ((size_m === `LM32_SIZE_WORD) && (load_store_address_m[1:0] !== 2'b00))
$display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time);
end
end
// synthesis translate_on
endmodule

View File

@@ -0,0 +1,71 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_logic_op.v
// Title : Logic operations (and / or / not etc)
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_logic_op (
// ----- Inputs -------
logic_op_x,
operand_0_x,
operand_1_x,
// ----- Outputs -------
logic_result_x
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input [`LM32_LOGIC_OP_RNG] logic_op_x;
input [`LM32_WORD_RNG] operand_0_x;
input [`LM32_WORD_RNG] operand_1_x;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] logic_result_x;
reg [`LM32_WORD_RNG] logic_result_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
integer logic_idx;
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
always @*
begin
for(logic_idx = 0; logic_idx < `LM32_WORD_WIDTH; logic_idx = logic_idx + 1)
logic_result_x[logic_idx] = logic_op_x[{operand_1_x[logic_idx], operand_0_x[logic_idx]}];
end
endmodule

View File

@@ -0,0 +1,283 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm_mc_arithmetic.v
// Title : Multi-cycle arithmetic unit.
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
`define LM32_MC_STATE_RNG 2:0
`define LM32_MC_STATE_IDLE 3'b000
`define LM32_MC_STATE_MULTIPLY 3'b001
`define LM32_MC_STATE_MODULUS 3'b010
`define LM32_MC_STATE_DIVIDE 3'b011
`define LM32_MC_STATE_SHIFT_LEFT 3'b100
`define LM32_MC_STATE_SHIFT_RIGHT 3'b101
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_mc_arithmetic (
// ----- Inputs -----
clk_i,
rst_i,
stall_d,
kill_x,
`ifdef CFG_MC_DIVIDE_ENABLED
divide_d,
modulus_d,
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
multiply_d,
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
shift_left_d,
shift_right_d,
sign_extend_d,
`endif
operand_0_d,
operand_1_d,
// ----- Ouputs -----
result_x,
`ifdef CFG_MC_DIVIDE_ENABLED
divide_by_zero_x,
`endif
stall_request_x
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_d; // Stall instruction in D stage
input kill_x; // Kill instruction in X stage
`ifdef CFG_MC_DIVIDE_ENABLED
input divide_d; // Perform divide
input modulus_d; // Perform modulus
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
input multiply_d; // Perform multiply
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
input shift_left_d; // Perform left shift
input shift_right_d; // Perform right shift
input sign_extend_d; // Whether to sign-extend (arithmetic) or zero-extend (logical)
`endif
input [`LM32_WORD_RNG] operand_0_d;
input [`LM32_WORD_RNG] operand_1_d;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] result_x; // Result of operation
reg [`LM32_WORD_RNG] result_x;
`ifdef CFG_MC_DIVIDE_ENABLED
output divide_by_zero_x; // A divide by zero was attempted
reg divide_by_zero_x;
`endif
output stall_request_x; // Request to stall pipeline from X stage back
wire stall_request_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [`LM32_WORD_RNG] p; // Temporary registers
reg [`LM32_WORD_RNG] a;
reg [`LM32_WORD_RNG] b;
`ifdef CFG_MC_DIVIDE_ENABLED
wire [32:0] t;
`endif
reg [`LM32_MC_STATE_RNG] state; // Current state of FSM
reg [5:0] cycles; // Number of cycles remaining in the operation
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
reg sign_extend_x; // Whether to sign extend of zero extend right shifts
wire fill_value; // Value to fill with for right barrel-shifts
`endif
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Stall pipeline while any operation is being performed
assign stall_request_x = state != `LM32_MC_STATE_IDLE;
`ifdef CFG_MC_DIVIDE_ENABLED
// Subtraction
assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b;
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1];
`endif
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
// Perform right shift
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
cycles <= {6{1'b0}};
p <= {`LM32_WORD_WIDTH{1'b0}};
a <= {`LM32_WORD_WIDTH{1'b0}};
b <= {`LM32_WORD_WIDTH{1'b0}};
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
sign_extend_x <= 1'b0;
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
divide_by_zero_x <= `FALSE;
`endif
result_x <= {`LM32_WORD_WIDTH{1'b0}};
state <= `LM32_MC_STATE_IDLE;
end
else
begin
`ifdef CFG_MC_DIVIDE_ENABLED
divide_by_zero_x <= `FALSE;
`endif
case (state)
`LM32_MC_STATE_IDLE:
begin
if (stall_d == `FALSE)
begin
cycles <= `LM32_WORD_WIDTH;
p <= 32'b0;
a <= operand_0_d;
b <= operand_1_d;
`ifdef CFG_MC_DIVIDE_ENABLED
if (divide_d == `TRUE)
state <= `LM32_MC_STATE_DIVIDE;
if (modulus_d == `TRUE)
state <= `LM32_MC_STATE_MODULUS;
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
if (multiply_d == `TRUE)
state <= `LM32_MC_STATE_MULTIPLY;
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
if (shift_left_d == `TRUE)
begin
state <= `LM32_MC_STATE_SHIFT_LEFT;
sign_extend_x <= sign_extend_d;
cycles <= operand_1_d[4:0];
a <= operand_0_d;
b <= operand_0_d;
end
if (shift_right_d == `TRUE)
begin
state <= `LM32_MC_STATE_SHIFT_RIGHT;
sign_extend_x <= sign_extend_d;
cycles <= operand_1_d[4:0];
a <= operand_0_d;
b <= operand_0_d;
end
`endif
end
end
`ifdef CFG_MC_DIVIDE_ENABLED
`LM32_MC_STATE_DIVIDE:
begin
if (t[32] == 1'b0)
begin
p <= t[31:0];
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
end
else
begin
p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
end
result_x <= a;
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
begin
// Check for divide by zero
divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
state <= `LM32_MC_STATE_IDLE;
end
cycles <= cycles - 1'b1;
end
`LM32_MC_STATE_MODULUS:
begin
if (t[32] == 1'b0)
begin
p <= t[31:0];
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
end
else
begin
p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
end
result_x <= p;
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
begin
// Check for divide by zero
divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
state <= `LM32_MC_STATE_IDLE;
end
cycles <= cycles - 1'b1;
end
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
`LM32_MC_STATE_MULTIPLY:
begin
if (b[0] == 1'b1)
p <= p + a;
b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]};
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
result_x <= p;
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
state <= `LM32_MC_STATE_IDLE;
cycles <= cycles - 1'b1;
end
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
`LM32_MC_STATE_SHIFT_LEFT:
begin
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
result_x <= a;
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
state <= `LM32_MC_STATE_IDLE;
cycles <= cycles - 1'b1;
end
`LM32_MC_STATE_SHIFT_RIGHT:
begin
b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]};
result_x <= b;
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
state <= `LM32_MC_STATE_IDLE;
cycles <= cycles - 1'b1;
end
`endif
endcase
end
end
endmodule

View File

@@ -0,0 +1,164 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_monitor.v
// Title : Debug monitor memory Wishbone interface
// Version : 6.1.17
// =============================================================================
`include "system_conf.v"
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_monitor (
// ----- Inputs -------
clk_i,
rst_i,
MON_ADR_I,
MON_CYC_I,
MON_DAT_I,
MON_SEL_I,
MON_STB_I,
MON_WE_I,
MON_LOCK_I,
MON_CTI_I,
MON_BTE_I,
// ----- Outputs -------
MON_ACK_O,
MON_RTY_O,
MON_DAT_O,
MON_ERR_O
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Wishbone clock
input rst_i; // Wishbone reset
input [`LM32_WORD_RNG] MON_ADR_I; // Wishbone address
input MON_STB_I; // Wishbone strobe
input MON_CYC_I; // Wishbone cycle
input [`LM32_WORD_RNG] MON_DAT_I; // Wishbone write data
input [`LM32_BYTE_SELECT_RNG] MON_SEL_I; // Wishbone byte select
input MON_WE_I; // Wishbone write enable
input MON_LOCK_I; // Wishbone locked transfer
input [`LM32_CTYPE_RNG] MON_CTI_I; // Wishbone cycle type
input [`LM32_BTYPE_RNG] MON_BTE_I; // Wishbone burst type
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output MON_ACK_O; // Wishbone acknowlege
reg MON_ACK_O;
output [`LM32_WORD_RNG] MON_DAT_O; // Wishbone data output
reg [`LM32_WORD_RNG] MON_DAT_O;
output MON_RTY_O; // Wishbone retry
wire MON_RTY_O;
output MON_ERR_O; // Wishbone error
wire MON_ERR_O;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [1:0] state; // Current state of FSM
wire [`LM32_WORD_RNG] data; // Data read from RAM
reg write_enable; // RAM write enable
reg [`LM32_WORD_RNG] write_data; // RAM write data
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
lm32_monitor_ram ram (
// ----- Inputs -------
.ClockA (clk_i),
.ClockB (clk_i),
.ResetA (rst_i),
.ResetB (rst_i),
.ClockEnA (`TRUE),
.ClockEnB (`FALSE),
.AddressA (MON_ADR_I[10:2]),
.DataInA (write_data),
.WrA (write_enable),
.WrB (`FALSE),
// ----- Outputs -------
.QA (data)
);
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
assign MON_RTY_O = `FALSE;
assign MON_ERR_O = `FALSE;
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
write_enable <= `FALSE;
MON_ACK_O <= `FALSE;
MON_DAT_O <= {`LM32_WORD_WIDTH{1'bx}};
state <= 2'b00;
end
else
begin
case (state)
2'b00:
begin
// Wait for a Wishbone access
if ((MON_STB_I == `TRUE) && (MON_CYC_I == `TRUE))
state <= 2'b01;
end
2'b01:
begin
// Output read data to Wishbone
MON_ACK_O <= `TRUE;
MON_DAT_O <= data;
// Sub-word writes are performed using read-modify-write
// as the Lattice EBRs don't support byte enables
if (MON_WE_I == `TRUE)
write_enable <= `TRUE;
write_data[7:0] <= MON_SEL_I[0] ? MON_DAT_I[7:0] : data[7:0];
write_data[15:8] <= MON_SEL_I[1] ? MON_DAT_I[15:8] : data[15:8];
write_data[23:16] <= MON_SEL_I[2] ? MON_DAT_I[23:16] : data[23:16];
write_data[31:24] <= MON_SEL_I[3] ? MON_DAT_I[31:24] : data[31:24];
state <= 2'b10;
end
2'b10:
begin
// Wishbone access occurs in this cycle
write_enable <= `FALSE;
MON_ACK_O <= `FALSE;
MON_DAT_O <= {`LM32_WORD_WIDTH{1'bx}};
state <= 2'b00;
end
endcase
end
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_multiplier.v
// Title : Pipelined multiplier.
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_multiplier (
// ----- Inputs -----
clk_i,
rst_i,
stall_x,
stall_m,
operand_0,
operand_1,
// ----- Ouputs -----
result
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_x; // Stall instruction in X stage
input stall_m; // Stall instruction in M stage
input [`LM32_WORD_RNG] operand_0; // Muliplicand
input [`LM32_WORD_RNG] operand_1; // Multiplier
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] result; // Product of multiplication
reg [`LM32_WORD_RNG] result;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [`LM32_WORD_RNG] muliplicand;
reg [`LM32_WORD_RNG] multiplier;
reg [`LM32_WORD_RNG] product;
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
muliplicand <= {`LM32_WORD_WIDTH{1'b0}};
multiplier <= {`LM32_WORD_WIDTH{1'b0}};
product <= {`LM32_WORD_WIDTH{1'b0}};
result <= {`LM32_WORD_WIDTH{1'b0}};
end
else
begin
if (stall_x == `FALSE)
begin
muliplicand <= operand_0;
multiplier <= operand_1;
end
if (stall_m == `FALSE)
product <= muliplicand * multiplier;
result <= product;
end
end
endmodule

View File

@@ -0,0 +1,105 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_ram.v
// Title : Pseudo dual-port RAM.
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_ram (
// ----- Inputs -------
read_clk,
write_clk,
reset,
enable_read,
read_address,
enable_write,
write_address,
write_data,
write_enable,
// ----- Outputs -------
read_data
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter data_width = 1; // Width of the data ports
parameter address_width = 1; // Width of the address ports
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input read_clk; // Read clock
input write_clk; // Write clock
input reset; // Reset
input enable_read; // Access enable
input [address_width-1:0] read_address; // Read/write address
input enable_write; // Access enable
input [address_width-1:0] write_address;// Read/write address
input [data_width-1:0] write_data; // Data to write to specified address
input write_enable; // Write enable
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [data_width-1:0] read_data; // Data read from specified addess
wire [data_width-1:0] read_data;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [data_width-1:0] mem[0:(1<<address_width)-1]; // The RAM
reg [address_width-1:0] ra; // Registered read address
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Read port
assign read_data = mem[ra];
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// Write port
always @(posedge write_clk)
begin
if ((write_enable == `TRUE) && (enable_write == `TRUE))
mem[write_address] <= write_data;
end
// Register read address for use on next cycle
always @(posedge read_clk)
begin
if (enable_read)
ra <= read_address;
end
endmodule

View File

@@ -0,0 +1,129 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_shifter.v
// Title : Barrel shifter
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_shifter (
// ----- Inputs -------
clk_i,
rst_i,
stall_x,
direction_x,
sign_extend_x,
operand_0_x,
operand_1_x,
// ----- Outputs -------
shifter_result_m
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_x; // Stall instruction in X stage
input direction_x; // Direction to shift
input sign_extend_x; // Whether shift is arithmetic (1'b1) or logical (1'b0)
input [`LM32_WORD_RNG] operand_0_x; // Operand to shift
input [`LM32_WORD_RNG] operand_1_x; // Operand that specifies how many bits to shift by
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] shifter_result_m; // Result of shift
wire [`LM32_WORD_RNG] shifter_result_m;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg direction_m;
reg [`LM32_WORD_RNG] left_shift_result;
reg [`LM32_WORD_RNG] right_shift_result;
reg [`LM32_WORD_RNG] left_shift_operand;
wire [`LM32_WORD_RNG] right_shift_operand;
wire fill_value;
wire [`LM32_WORD_RNG] right_shift_in;
integer shift_idx_0;
integer shift_idx_1;
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Select operands - To perform a left shift, we reverse the bits and perform a right shift
always @*
begin
for (shift_idx_0 = 0; shift_idx_0 < `LM32_WORD_WIDTH; shift_idx_0 = shift_idx_0 + 1)
left_shift_operand[`LM32_WORD_WIDTH-1-shift_idx_0] = operand_0_x[shift_idx_0];
end
assign right_shift_operand = direction_x == `LM32_SHIFT_OP_LEFT ? left_shift_operand : operand_0_x;
// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
assign fill_value = (sign_extend_x == `TRUE) && (direction_x == `LM32_SHIFT_OP_RIGHT)
? operand_0_x[`LM32_WORD_WIDTH-1]
: 1'b0;
// Determine bits to shift in for right shift or rotate
assign right_shift_in = {`LM32_WORD_WIDTH{fill_value}};
// Reverse bits to get left shift result
always @*
begin
for (shift_idx_1 = 0; shift_idx_1 < `LM32_WORD_WIDTH; shift_idx_1 = shift_idx_1 + 1)
left_shift_result[`LM32_WORD_WIDTH-1-shift_idx_1] = right_shift_result[shift_idx_1];
end
// Select result
assign shifter_result_m = direction_m == `LM32_SHIFT_OP_LEFT ? left_shift_result : right_shift_result;
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// Perform right shift
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
right_shift_result <= {`LM32_WORD_WIDTH{1'b0}};
direction_m <= `FALSE;
end
else
begin
if (stall_x == `FALSE)
begin
right_shift_result <= {right_shift_in, right_shift_operand} >> operand_1_x[`LM32_SHIFT_RNG];
direction_m <= direction_x;
end
end
end
endmodule

View File

@@ -0,0 +1,165 @@
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_simtrace.v
// Title : Trace excecution in simulation
// Dependencies : lm32_include.v
// Version : soc-lm32 only
// =============================================================================
`include "lm32_include.v"
// Index of opcode field in an instruction
`define LM32_OPCODE_RNG 31:26
`define LM32_OP_RNG 30:26
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_simtrace (
// ----- Inputs -------
clk_i,
rst_i,
// From pipeline
stall_x,
stall_m,
valid_w,
kill_w,
instruction_d,
pc_w
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i;
input rst_i;
input stall_x; //
input stall_m; //
input valid_w; //
input kill_w; //
input [`LM32_INSTRUCTION_RNG] instruction_d; // Instruction to decode
input [`LM32_PC_RNG] pc_w; // PC of instruction in D stage
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [`LM32_INSTRUCTION_RNG] instruction_x; // Instruction to decode
reg [`LM32_INSTRUCTION_RNG] instruction_m; // Instruction to decode
reg [`LM32_INSTRUCTION_RNG] instruction; // Instruction to decode
wire [`LM32_WORD_RNG] extended_immediate; // Zero or sign extended immediate
wire [`LM32_WORD_RNG] high_immediate; // Immedate as high 16 bits
wire [`LM32_WORD_RNG] immediate; // Immedate as high 16 bits
wire [`LM32_WORD_RNG] call_immediate; // Call immediate
wire [`LM32_WORD_RNG] branch_immediate; // Conditional branch immediate
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
wire [4:0] r3 = instruction[25:21];
wire [4:0] r2 = instruction[20:16];
wire [4:0] r1 = instruction[15:11];
wire [ 4:0] imm5 = instruction[ 4:0];
wire [15:0] imm16 = instruction[15:0];
wire [26:0] imm27 = instruction[26:0];
//assign high_imm = {instruction[15:0], 16'h0000};
wire [`LM32_PC_RNG] call_imm = {{ 4{instruction[25]}}, instruction[25:0]};
wire [`LM32_PC_RNG] branch_imm = {{14{instruction[15]}}, instruction[15:0] };
// synopsys translate_off
always @(posedge clk_i)
begin
if (stall_x == `FALSE)
instruction_x <= instruction_d;
if (stall_m == `FALSE)
instruction_m <= instruction_x;
instruction <= instruction_m;
if ((valid_w == `TRUE) && (!kill_w)) begin
// $write ( $stime/10 );
$writeh( " [", pc_w << 2);
$writeh( "]\t" );
case ( instruction[`LM32_OPCODE_RNG] )
6'h00: $display( "srui r%0d, r%0d, 0x%0x", r2, r3, imm5 );
6'h01: $display( "nori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h02: $display( "muli r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h03: $display( "sh (r%0d + 0x%0x), r%0d", r3, r2, imm16 );
6'h04: $display( "lb r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
6'h05: $display( "sri r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h06: $display( "xori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h07: $display( "lh r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
6'h08: $display( "andi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h09: $display( "xnori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h0a: $display( "lw r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
6'h0b: $display( "lhu r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
6'h0c: $display( "sb (r%0d + 0x%0x), r%0d", r3, r2, imm16 );
6'h0d: $display( "addi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h0e: $display( "ori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h0f: $display( "sli r%0d, r%0d, 0x%0x", r2, r3, imm5 );
6'h10: $display( "lbu r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
6'h11: $display( "be r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
6'h12: $display( "bg r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
6'h13: $display( "bge r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
6'h14: $display( "bgeu r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
6'h15: $display( "bgu r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
6'h16: $display( "sw (r%0d + 0x%0x), r%0d", r3, r2, imm16 );
6'h17: $display( "bne r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
6'h18: $display( "andhi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h19: $display( "cmpei r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h1a: $display( "cmpgi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h1b: $display( "cmpgei r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h1c: $display( "cmpgeui r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h1d: $display( "cmpgui r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h1e: $display( "orhi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h1f: $display( "cmpnei r%0d, r%0d, 0x%0x", r2, r3, imm16 );
6'h20: $display( "sru r%0d, r%0d, r%0d", r1, r3, r2 );
6'h21: $display( "nor r%0d, r%0d, r%0d", r1, r3, r2 );
6'h22: $display( "mul r%0d, r%0d, r%0d", r1, r3, r2 );
6'h23: $display( "divu r%0d, r%0d, r%0d", r1, r3, r2 );
6'h24: $display( "rcsr r%0d, csr%0d", r1, r3 );
6'h25: $display( "sr r%0d, r%0d, r%0d", r1, r3, r2 );
6'h26: $display( "xor r%0d, r%0d, r%0d", r1, r3, r2 );
6'h27: $display( "div (XXX not documented XXX)" );
6'h28: $display( "and r%0d, r%0d, r%0d", r1, r3, r2 );
6'h29: $display( "xnor r%0d, r%0d, r%0d", r1, r3, r2 );
6'h2a: $display( "XXX" );
6'h2b: $display( "raise (XXX: scall or break)" );
6'h2c: $display( "sextb r%0d, r%0d", r1, r3 );
6'h2d: $display( "add r%0d, r%0d, r%0d", r1, r3, r2 );
6'h2e: $display( "or r%0d, r%0d, r%0d", r1, r3, r2 );
6'h2f: $display( "sl r%0d, r%0d, r%0d", r1, r3, r2 );
6'h30: $display( "b r%0d", r3 );
6'h31: $display( "modu r%0d, r%0d, r%0d", r1, r3, r2 );
6'h32: $display( "sub r%0d, r%0d, r%0d", r1, r3, r2 );
6'h33: $display( "XXX" );
6'h34: $display( "wcsr csr%0d, r%0d", r3, r2 );
6'h35: $display( "modu r%0d, r%0d, r%0d", r1, r3, r2 );
6'h36: $display( "call r%0d", r3 );
6'h37: $display( "sexth r%0d, r%0d", r1, r3 );
6'h38: $display( "bi 0x%x", (pc_w + call_imm) << 2 );
6'h39: $display( "cmpe r%0d, r%0d, r%0d", r1, r3, r2 );
6'h3a: $display( "cmpg r%0d, r%0d, r%0d", r1, r3, r2 );
6'h3b: $display( "cmpge r%0d, r%0d, r%0d", r1, r3, r2 );
6'h3c: $display( "cmpgeu r%0d, r%0d, r%0d", r1, r3, r2 );
6'h3d: $display( "cmpgu r%0d, r%0d, r%0d", r1, r3, r2 );
6'h3e: $display( "calli 0x%x", (pc_w + call_imm) << 2 );
6'h3f: $display( "cmpne r%0d, r%0d, r%0d", r1, r3, r2 );
endcase
end
end
// synopsys translate_on
endmodule

View File

@@ -0,0 +1,370 @@
// =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_top.v
// Title : Top-level of CPU.
// Dependencies : lm32_include.v
// Version : 6.1.17
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_top (
// ----- Inputs -------
clk_i,
rst_i,
// From external devices
`ifdef CFG_INTERRUPTS_ENABLED
interrupt_n,
`endif
// From user logic
`ifdef CFG_USER_ENABLED
user_result,
user_complete,
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone master
I_DAT_I,
I_ACK_I,
I_ERR_I,
I_RTY_I,
`endif
// Data Wishbone master
D_DAT_I,
D_ACK_I,
D_ERR_I,
D_RTY_I,
// Debug Slave port WishboneInterface
DEBUG_ADR_I,
DEBUG_DAT_I,
DEBUG_SEL_I,
DEBUG_WE_I,
DEBUG_CTI_I,
DEBUG_BTE_I,
DEBUG_LOCK_I,
DEBUG_CYC_I,
DEBUG_STB_I,
// ----- Outputs -------
`ifdef CFG_USER_ENABLED
user_valid,
user_opcode,
user_operand_0,
user_operand_1,
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone master
I_DAT_O,
I_ADR_O,
I_CYC_O,
I_SEL_O,
I_STB_O,
I_WE_O,
I_CTI_O,
I_LOCK_O,
I_BTE_O,
`endif
// Data Wishbone master
D_DAT_O,
D_ADR_O,
D_CYC_O,
D_SEL_O,
D_STB_O,
D_WE_O,
D_CTI_O,
D_LOCK_O,
D_BTE_O,
// Debug Slave port WishboneInterface
DEBUG_ACK_O,
DEBUG_ERR_O,
DEBUG_RTY_O,
DEBUG_DAT_O
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
`ifdef CFG_INTERRUPTS_ENABLED
input [`LM32_INTERRUPT_RNG] interrupt_n; // Interrupt pins, active-low
`endif
`ifdef CFG_USER_ENABLED
input [`LM32_WORD_RNG] user_result; // User-defined instruction result
input user_complete; // Indicates the user-defined instruction result is valid
`endif
`ifdef CFG_IWB_ENABLED
input [`LM32_WORD_RNG] I_DAT_I; // Instruction Wishbone interface read data
input I_ACK_I; // Instruction Wishbone interface acknowledgement
input I_ERR_I; // Instruction Wishbone interface error
input I_RTY_I; // Instruction Wishbone interface retry
`endif
input [`LM32_WORD_RNG] D_DAT_I; // Data Wishbone interface read data
input D_ACK_I; // Data Wishbone interface acknowledgement
input D_ERR_I; // Data Wishbone interface error
input D_RTY_I; // Data Wishbone interface retry
input [`LM32_WORD_RNG] DEBUG_ADR_I; // Debug monitor Wishbone interface address
input [`LM32_WORD_RNG] DEBUG_DAT_I; // Debug monitor Wishbone interface write data
input [`LM32_BYTE_SELECT_RNG] DEBUG_SEL_I; // Debug monitor Wishbone interface byte select
input DEBUG_WE_I; // Debug monitor Wishbone interface write enable
input [`LM32_CTYPE_RNG] DEBUG_CTI_I; // Debug monitor Wishbone interface cycle type
input [`LM32_BTYPE_RNG] DEBUG_BTE_I; // Debug monitor Wishbone interface burst type
input DEBUG_LOCK_I; // Debug monitor Wishbone interface locked transfer
input DEBUG_CYC_I; // Debug monitor Wishbone interface cycle
input DEBUG_STB_I; // Debug monitor Wishbone interface strobe
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
`ifdef CFG_USER_ENABLED
output user_valid; // Indicates that user_opcode and user_operand_* are valid
wire user_valid;
output [`LM32_USER_OPCODE_RNG] user_opcode; // User-defined instruction opcode
reg [`LM32_USER_OPCODE_RNG] user_opcode;
output [`LM32_WORD_RNG] user_operand_0; // First operand for user-defined instruction
wire [`LM32_WORD_RNG] user_operand_0;
output [`LM32_WORD_RNG] user_operand_1; // Second operand for user-defined instruction
wire [`LM32_WORD_RNG] user_operand_1;
`endif
`ifdef CFG_IWB_ENABLED
output [`LM32_WORD_RNG] I_DAT_O; // Instruction Wishbone interface write data
wire [`LM32_WORD_RNG] I_DAT_O;
output [`LM32_WORD_RNG] I_ADR_O; // Instruction Wishbone interface address
wire [`LM32_WORD_RNG] I_ADR_O;
output I_CYC_O; // Instruction Wishbone interface cycle
wire I_CYC_O;
output [`LM32_BYTE_SELECT_RNG] I_SEL_O; // Instruction Wishbone interface byte select
wire [`LM32_BYTE_SELECT_RNG] I_SEL_O;
output I_STB_O; // Instruction Wishbone interface strobe
wire I_STB_O;
output I_WE_O; // Instruction Wishbone interface write enable
wire I_WE_O;
output [`LM32_CTYPE_RNG] I_CTI_O; // Instruction Wishbone interface cycle type
wire [`LM32_CTYPE_RNG] I_CTI_O;
output I_LOCK_O; // Instruction Wishbone interface lock bus
wire I_LOCK_O;
output [`LM32_BTYPE_RNG] I_BTE_O; // Instruction Wishbone interface burst type
wire [`LM32_BTYPE_RNG] I_BTE_O;
`endif
output [`LM32_WORD_RNG] D_DAT_O; // Data Wishbone interface write data
wire [`LM32_WORD_RNG] D_DAT_O;
output [`LM32_WORD_RNG] D_ADR_O; // Data Wishbone interface address
wire [`LM32_WORD_RNG] D_ADR_O;
output D_CYC_O; // Data Wishbone interface cycle
wire D_CYC_O;
output [`LM32_BYTE_SELECT_RNG] D_SEL_O; // Data Wishbone interface byte select
wire [`LM32_BYTE_SELECT_RNG] D_SEL_O;
output D_STB_O; // Data Wishbone interface strobe
wire D_STB_O;
output D_WE_O; // Data Wishbone interface write enable
wire D_WE_O;
output [`LM32_CTYPE_RNG] D_CTI_O; // Data Wishbone interface cycle type
wire [`LM32_CTYPE_RNG] D_CTI_O;
output D_LOCK_O; // Date Wishbone interface lock bus
wire D_LOCK_O;
output [`LM32_BTYPE_RNG] D_BTE_O; // Data Wishbone interface burst type
wire [`LM32_BTYPE_RNG] D_BTE_O;
output DEBUG_ACK_O; // Debug monitor Wishbone ack
wire DEBUG_ACK_O;
output DEBUG_ERR_O; // Debug monitor Wishbone error
wire DEBUG_ERR_O;
output DEBUG_RTY_O; // Debug monitor Wishbone retry
wire DEBUG_RTY_O;
output [`LM32_WORD_RNG] DEBUG_DAT_O; // Debug monitor Wishbone read data
wire [`LM32_WORD_RNG] DEBUG_DAT_O;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
`ifdef CFG_JTAG_ENABLED
// Signals between JTAG interface and CPU
wire [`LM32_BYTE_RNG] jtag_reg_d;
wire [`LM32_BYTE_RNG] jtag_reg_q;
wire jtag_update;
wire [2:0] jtag_reg_addr_d;
wire [2:0] jtag_reg_addr_q;
wire jtck;
wire jrstn;
`endif
`ifdef CFG_TRACE_ENABLED
// PC trace signals
wire [`LM32_PC_RNG] trace_pc; // PC to trace (address of next non-sequential instruction)
wire trace_pc_valid; // Indicates that a new trace PC is valid
wire trace_exception; // Indicates an exception has occured
wire [`LM32_EID_RNG] trace_eid; // Indicates what type of exception has occured
wire trace_eret; // Indicates an eret instruction has been executed
`ifdef CFG_DEBUG_ENABLED
wire trace_bret; // Indicates a bret instruction has been executed
`endif
`endif
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
// LM32 CPU
lm32_cpu cpu (
// ----- Inputs -------
.clk_i (clk_i),
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
.clk_n_i (clk_n),
`endif
.rst_i (rst_i),
// From external devices
`ifdef CFG_INTERRUPTS_ENABLED
.interrupt_n (interrupt_n),
`endif
// From user logic
`ifdef CFG_USER_ENABLED
.user_result (user_result),
.user_complete (user_complete),
`endif
`ifdef CFG_JTAG_ENABLED
// From JTAG
.jtag_clk (jtck),
.jtag_update (jtag_update),
.jtag_reg_q (jtag_reg_q),
.jtag_reg_addr_q (jtag_reg_addr_q),
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone master
.I_DAT_I (I_DAT_I),
.I_ACK_I (I_ACK_I),
.I_ERR_I (I_ERR_I),
.I_RTY_I (I_RTY_I),
`endif
// Data Wishbone master
.D_DAT_I (D_DAT_I),
.D_ACK_I (D_ACK_I),
.D_ERR_I (D_ERR_I),
.D_RTY_I (D_RTY_I),
// ----- Outputs -------
`ifdef CFG_TRACE_ENABLED
.trace_pc (trace_pc),
.trace_pc_valid (trace_pc_valid),
.trace_exception (trace_exception),
.trace_eid (trace_eid),
.trace_eret (trace_eret),
`ifdef CFG_DEBUG_ENABLED
.trace_bret (trace_bret),
`endif
`endif
`ifdef CFG_JTAG_ENABLED
.jtag_reg_d (jtag_reg_d),
.jtag_reg_addr_d (jtag_reg_addr_d),
`endif
`ifdef CFG_USER_ENABLED
.user_valid (user_valid),
.user_opcode (user_opcode),
.user_operand_0 (user_operand_0),
.user_operand_1 (user_operand_1),
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone master
.I_DAT_O (I_DAT_O),
.I_ADR_O (I_ADR_O),
.I_CYC_O (I_CYC_O),
.I_SEL_O (I_SEL_O),
.I_STB_O (I_STB_O),
.I_WE_O (I_WE_O),
.I_CTI_O (I_CTI_O),
.I_LOCK_O (I_LOCK_O),
.I_BTE_O (I_BTE_O),
`endif
// Data Wishbone master
.D_DAT_O (D_DAT_O),
.D_ADR_O (D_ADR_O),
.D_CYC_O (D_CYC_O),
.D_SEL_O (D_SEL_O),
.D_STB_O (D_STB_O),
.D_WE_O (D_WE_O),
.D_CTI_O (D_CTI_O),
.D_LOCK_O (D_LOCK_O),
.D_BTE_O (D_BTE_O)
);
`ifdef DEBUG_ROM
// ROM monitor
lm32_monitor debug_rom (
// ----- Inputs -------
.clk_i (clk_i),
.rst_i (rst_i),
.MON_ADR_I (DEBUG_ADR_I),
.MON_STB_I (DEBUG_STB_I),
.MON_CYC_I (DEBUG_CYC_I),
.MON_WE_I (DEBUG_WE_I),
.MON_SEL_I (DEBUG_SEL_I),
.MON_DAT_I (DEBUG_DAT_I),
.MON_CTI_I (DEBUG_CTI_I),
.MON_BTE_I (DEBUG_BTE_I),
.MON_LOCK_I (DEBUG_LOCK_I),
// ----- Outputs ------
.MON_RTY_O (DEBUG_RTY_O),
.MON_ERR_O (DEBUG_ERR_O),
.MON_ACK_O (DEBUG_ACK_O),
.MON_DAT_O (DEBUG_DAT_O)
);
`endif
`ifdef CFG_JTAG_ENABLED
// JTAG cores
jtag_cores jtag_cores (
// ----- Inputs -----
`ifdef INCLUDE_LM32
.reg_d (jtag_reg_d),
.reg_addr_d (jtag_reg_addr_d),
`endif
`ifdef INCLUDE_SPI
.spi_q (spi_q),
`endif
// ----- Outputs -----
`ifdef INCLUDE_LM32
.reg_update (jtag_update),
.reg_q (jtag_reg_q),
.reg_addr_q (jtag_reg_addr_q),
`endif
`ifdef INCLUDE_SPI
.spi_c (spi_c),
.spi_d (spi_d),
.spi_sn (spi_sn),
`endif
.jtck (jtck),
.jrstn (jrstn)
);
`endif
endmodule

View File

@@ -0,0 +1,159 @@
//---------------------------------------------------------------------------
//
//Name : SPIPROG.v
//
//Description:
//
// This module contains the ER2 regsiters of SPI Serial FLASH programmer IP
// core. There are only three ER2 registers, one control register and two
// data registers, in this IP core. The control register is a 8-bit wide
// register for selecting which data register will be accessed when the
// Control/Data# bit in ER1 register is low. Data register 0 is a readonly
// ID register. It is composed of three register fields -- an 8-bit
// "implementer", a 16-bit "IP_functionality", and a 12-bit "revision".
// Data register 1 is a variable length register for sending commands to or
// receiving readback data from the SPI Serial FLASH device.
//
//$Log: spiprog.vhd,v $
//Revision 1.2 2004-09-09 11:43:26-07 jhsin
//1. Reduced the the ID register (DR0) length from 36 bits to 8 bits.
//2. Same as TYPEA and TYPEB modules, use falling edge clock
// for all TCK Flip-Flops.
//
//Revision 1.1 2004-08-12 13:22:05-07 jhsin
//Added 7 delay Flip-Flops so that the DR1 readback data from SPI Serial FLASH is in the byte boundary.
//
//Revision 1.0 2004-08-03 18:35:56-07 jhsin
//Initial revision
//
//
//$Header: \\\\hqfs2\\ip\040cores\\rcs\\hqfs2\\ip\040cores\\rcswork\\isptracy\\VHDL\\Implementation\\spiprog.vhd,v 1.2 2004-09-09 11:43:26-07 jhsin Exp $
//
//Copyright (C) 2004 Lattice Semiconductor Corp. All rights reserved.
//
//---------------------------------------------------------------------------
module SPIPROG (input JTCK ,
input JTDI ,
output JTDO2 ,
input JSHIFT ,
input JUPDATE ,
input JRSTN ,
input JCE2 ,
input SPIPROG_ENABLE ,
input CONTROL_DATAN ,
output SPI_C ,
output SPI_D ,
output SPI_SN ,
input SPI_Q);
wire er2Cr_enable ;
wire er2Dr0_enable;
wire er2Dr1_enable;
wire tdo_er2Cr ;
wire tdo_er2Dr0;
wire tdo_er2Dr1;
wire [7:0] encodedDrSelBits ;
wire [8:0] er2CrTdiBit ;
wire [8:0] er2Dr0TdiBit ;
wire captureDrER2;
reg spi_s ;
reg [6:0] spi_q_dly;
wire [7:0] ip_functionality_id;
genvar i;
// ------ Control Register 0 ------
assign er2Cr_enable = JCE2 & SPIPROG_ENABLE & CONTROL_DATAN;
assign tdo_er2Cr = er2CrTdiBit[0];
// CR_BIT0_BIT7
generate
for(i=0; i<=7; i=i+1)
begin:CR_BIT0_BIT7
TYPEA BIT_N (.CLK (JTCK),
.RESET_N (JRSTN),
.CLKEN (er2Cr_enable),
.TDI (er2CrTdiBit[i + 1]),
.TDO (er2CrTdiBit[i]),
.DATA_OUT (encodedDrSelBits[i]),
.DATA_IN (encodedDrSelBits[i]),
.CAPTURE_DR (captureDrER2),
.UPDATE_DR (JUPDATE));
end
endgenerate // CR_BIT0_BIT7
assign er2CrTdiBit[8] = JTDI;
// ------ Data Register 0 ------
assign er2Dr0_enable = (JCE2 & SPIPROG_ENABLE & ~CONTROL_DATAN & (encodedDrSelBits == 8'b00000000)) ? 1'b1 : 1'b0;
assign tdo_er2Dr0 = er2Dr0TdiBit[0];
assign ip_functionality_id = 8'b00000001; //-- SPI Serial FLASH Programmer (0x01)
// DR0_BIT0_BIT7
generate
for(i=0; i<=7; i=i+1)
begin:DR0_BIT0_BIT7
TYPEB BIT_N (.CLK (JTCK),
.RESET_N (JRSTN),
.CLKEN (er2Dr0_enable),
.TDI (er2Dr0TdiBit[i + 1]),
.TDO (er2Dr0TdiBit[i]),
.DATA_IN (ip_functionality_id[i]),
.CAPTURE_DR (captureDrER2));
end
endgenerate // DR0_BIT0_BIT7
assign er2Dr0TdiBit[8] = JTDI;
// ------ Data Register 1 ------
assign er2Dr1_enable = (JCE2 & JSHIFT & SPIPROG_ENABLE & ~CONTROL_DATAN & (encodedDrSelBits == 8'b00000001)) ? 1'b1 : 1'b0;
assign SPI_C = ~ (JTCK & er2Dr1_enable & spi_s);
assign SPI_D = JTDI & er2Dr1_enable;
// SPI_S_Proc
always @(negedge JTCK or negedge JRSTN)
begin
if (~JRSTN)
spi_s <= 1'b0;
else
if (JUPDATE)
spi_s <= 1'b0;
else
spi_s <= er2Dr1_enable;
end
assign SPI_SN = ~spi_s;
// SPI_Q_Proc
always @(negedge JTCK or negedge JRSTN)
begin
if (~JRSTN)
spi_q_dly <= 'b0;
else
if (er2Dr1_enable)
spi_q_dly <= {spi_q_dly[5:0],SPI_Q};
end
assign tdo_er2Dr1 = spi_q_dly[6];
// ------ JTDO2 MUX ------
assign JTDO2 = CONTROL_DATAN ? tdo_er2Cr :
(encodedDrSelBits == 8'b00000000) ? tdo_er2Dr0 :
(encodedDrSelBits == 8'b00000001) ? tdo_er2Dr1 : 1'b0;
assign captureDrER2 = ~JSHIFT & JCE2;
endmodule

View File

@@ -0,0 +1,58 @@
# Synplicity, Inc. constraint file
# C:\ispTOOLS6_0\micosystem\components\lm32_top\rtl\verilog\system.sdc
# Written on Thu Apr 06 13:56:58 2006
# by Synplify for Lattice, Synplify for Lattice 8.5D Scope Editor
#
# Clocks
#
define_clock -name {clk_i} -freq 25.000 -clockgroup default_clkgroup_0
#
# Clock to Clock
#
#
# Inputs/Outputs
#
#
# Registers
#
#
# Multicycle Path
#
#
# False Path
#
#
# Path Delay
#
#
# Attributes
#
define_attribute {clk_i} loc {a10}
define_attribute {reset_n} loc {h6}
define_attribute {uartSIN} loc {m2}
define_attribute {uartSOUT} loc {l1}
define_attribute {sramsram_csn} loc {y4}
define_attribute {sramsram_oen} loc {aa6}
define_attribute {sramsram_wen} loc {ab6}
define_attribute {sramsram_be[3:0]} loc {aa3,ab3,aa4,ab4}
define_attribute {sramsram_data[31:0]} loc {v7,w7,y7,aa7,ab7,v8,w8,y8,aa8,ab8,v9,w9,y9,aa9,ab9,v10,w10,y10,aa10,w11,y11,aa11,y13,aa13,w14,y14,aa14,ab14,u15,v15,w15,y15}
define_attribute {sramsram_addr[22:0]} loc {u16,v16,w16,y16,aa16,ab16,u17,v17,w17,y17,aa17,ab17,w18,y18,aa18,ab18,y19,aa19,ab19,aa20,ab20,y20,w20}
define_attribute {gpio_LCDPIO_OUT[15:0]} loc {h5,t13,t17,u13,v13,p5,p3,p4,n5,n4,n3,n2,n1,m5,m4,m3}
define_attribute {gpio_LEDPIO_OUT[9:0]} loc {u11,v5,u6,u4,g5,g4,f5,f4,e5,e4}
define_attribute {gpio_KeypadPIO_IN[3:0]} loc {R1,T3,T2,T1}
#
# I/O standards
#
#
# Other Constraints
#

View File

@@ -0,0 +1,74 @@
/*-- ---------------------------------------------------------------------------
--
-- Name : TYPEA.v
--
-- Description:
--
-- This is one of the two types of cells that are used to create ER1/ER2
-- register bits.
--
-- $Log: typea.vhd,v $
-- Revision 1.2 2002-11-13 18:33:59-08 jhsin
-- The SHIFT_DR_CAPTURE_DR and ENABLE_ER1/2 signals of the
-- dedicate logic JTAG_PORT didn't act as what their names implied.
-- The SHIFT_DR_CAPTURE_DR actually acts as SHIFT_DR.
-- The ENABLE_ER1/2 actually acts as SHIFT_DR_CAPTURE_DR.
-- These had caused a lot of headaches for a long time and now they are
-- fixed by:
-- (1) Use SHIFT_DR_CAPTURE_DR and ENABLE_ER1/2 to create
-- CAPTURE_DR for all typeA, typeB bits in the ER1, ER2 registers.
-- (2) Use ENABLE_ER1 or the enESR, enCSR, enBAR (these 3 signals
-- have the same waveform of ENABLE_ER2) directly to be the CLKEN
-- of all typeA, typeB bits in the ER1, ER2 registers.
-- (3) Modify typea.vhd to use only UPDATE_DR signal for the clock enable
-- of the holding flip-flop.
-- These changes caused ispTracy.vhd and cge.dat changes and the new
-- CGE.exe version will be 1.3.5.
--
-- Revision 1.1 2002-05-01 18:13:51-07 jhsin
-- Added RCS version control header to file. No code changes.
--
-- $Header: \\\\hqfile2\\ipcores\\rcs\\hqfile2\\ipcores\\rcswork\\isptracy\\VHDL\\Implementation\\typea.vhd,v 1.2 2002-11-13 18:33:59-08 jhsin Exp $
--
-- Copyright (C) 2002 Lattice Semiconductor Corp. All rights reserved.
--
-- ---------------------------------------------------------------------------*/
module TYPEA(
input CLK,
input RESET_N,
input CLKEN,
input TDI,
output TDO,
output reg DATA_OUT,
input DATA_IN,
input CAPTURE_DR,
input UPDATE_DR
);
reg tdoInt;
always @ (negedge CLK or negedge RESET_N)
begin
if (RESET_N == 1'b0)
tdoInt <= 1'b0;
else if (CLK == 1'b0)
if (CLKEN == 1'b1)
if (CAPTURE_DR == 1'b0)
tdoInt <= TDI;
else
tdoInt <= DATA_IN;
end
assign TDO = tdoInt;
always @ (negedge CLK or negedge RESET_N)
begin
if (RESET_N == 1'b0)
DATA_OUT <= 1'b0;
else if (CLK == 1'b0)
if (UPDATE_DR == 1'b1)
DATA_OUT <= tdoInt;
end
endmodule

View File

@@ -0,0 +1,50 @@
/*-- ---------------------------------------------------------------------------
--
-- Name : TYPEB.vhd
--
-- Description:
--
-- This is one of the two types of cells that are used to create ER1/ER2
-- register bits.
--
-- $Log: typeb.vhd,v $
-- Revision 1.2 2002-08-01 16:39:33-07 jhsin
-- Modified typeb module to remove redundant DATA_OUT port.
--
-- Revision 1.1 2002-05-01 18:13:51-07 jhsin
-- Added RCS version control header to file. No code changes.
--
-- $Header: \\\\hqfile2\\ipcores\\rcs\\hqfile2\\ipcores\\rcswork\\isptracy\\VHDL\\Implementation\\typeb.vhd,v 1.2 2002-08-01 16:39:33-07 jhsin Exp $
--
-- Copyright (C) 2002 Lattice Semiconductor Corp. All rights reserved.
--
-- ---------------------------------------------------------------------------*/
module TYPEB
(
input CLK,
input RESET_N,
input CLKEN,
input TDI,
output TDO,
input DATA_IN,
input CAPTURE_DR
);
reg tdoInt;
always @ (negedge CLK or negedge RESET_N)
begin
if (RESET_N== 1'b0)
tdoInt <= 1'b0;
else if (CLK == 1'b0)
if (CLKEN==1'b1)
if (CAPTURE_DR==1'b0)
tdoInt <= TDI;
else
tdoInt <= DATA_IN;
end
assign TDO = tdoInt;
endmodule