Last active
October 17, 2021 22:39
-
-
Save gabonator/9979a3057245ea6ccc9b7994612e86cd to your computer and use it in GitHub Desktop.
alta gate vhdl spi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////// | |
// Copyright (c)2013 ALTAGATE CO.,Ltd // | |
// All Rights Reserved // | |
// No part of this code may be reproduced, stored in a retrieval system, // | |
// or transmitted, in any form or by any means, electronic, mechanical, // | |
// photocopying, recording, or otherwise, without the prior written // | |
// permission of ALTAGATE CO.,Ltd // | |
///////////////////////////////////////////////////////////////////////////// | |
`timescale 1ns/10ps | |
// synopsys translate_off | |
`define ALTA_SIM | |
// synopsys translate_on | |
`ifdef ALTA_SIM | |
`define TRI1 tri1 | |
`define TRI0 tri0 | |
`else | |
`define TRI1 wire | |
`define TRI0 wire | |
`endif | |
`ifndef PLL_RESOLUTION | |
`define PLL_RESOLUTION 1ns/10fs | |
`endif | |
module alta_slice ( | |
input A, B, C, D, Cin, Qin, | |
input Clk, AsyncReset, SyncReset, ShiftData, SyncLoad, | |
output Cout, LutOut, | |
output reg Q | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter mask = 16'h0000; | |
parameter modeMux = 1'b0; | |
parameter mode = "logic"; | |
parameter FeedbackMux = 1'b1; | |
parameter ShiftMux = 1'b0; | |
parameter BypassEn = 1'b0; | |
parameter CarryEnb = 1'b0; | |
parameter AsyncResetMux = 2'bxx; | |
parameter SyncResetMux = 2'bxx; | |
parameter SyncLoadMux = 2'bxx; | |
wire pinC = modeMux ? Cin : (FeedbackMux ? Qin : C); | |
assign LutOut = D ? ( pinC ? ( B ? ( A ? mask[15] : mask[14]) : ( A ? mask[13] : mask[12])) | |
: ( B ? ( A ? mask[11] : mask[10]) : ( A ? mask[ 9] : mask[ 8]))) | |
: ( pinC ? ( B ? ( A ? mask[ 7] : mask[ 6]) : ( A ? mask[ 5] : mask[ 4])) | |
: ( B ? ( A ? mask[ 3] : mask[ 2]) : ( A ? mask[ 1] : mask[ 0]))); | |
assign Cout = (Cin ? ( B ? ( A ? mask[ 7] : mask[ 6]) : ( A ? mask[ 5] : mask[ 4])) | |
: ( B ? ( A ? mask[ 3] : mask[ 2]) : ( A ? mask[ 1] : mask[ 0]))) | CarryEnb; | |
wire Din = !(BypassEn & SyncReset) & ((SyncLoad & BypassEn) ? C : (ShiftMux ? ShiftData : LutOut)); | |
initial Q = 1'b0; | |
always @ (posedge Clk or posedge AsyncReset) | |
begin | |
if (AsyncReset === 1'b1) | |
Q <= 1'b0; | |
else | |
Q <= Din; | |
end | |
endmodule | |
module alta_clkenctrl_rst ( | |
input ClkIn, ClkEn, Rst, | |
output ClkOut | |
); | |
reg ClkEn_reg = 1'b0; | |
always @ (ClkIn or ClkEn or Rst) begin | |
if (Rst) | |
ClkEn_reg <= 1'b0; | |
else if (ClkIn == 1'b0) | |
ClkEn_reg <= ClkEn; | |
end | |
assign ClkOut = ClkEn_reg & ClkIn; | |
endmodule | |
module alta_clkenctrl ( | |
input ClkIn, ClkEn, | |
output ClkOut | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter ClkMux = 2'b10; | |
parameter ClkEnMux = 2'b10; | |
wire ClkMuxOut = ClkMux[1] ? (ClkMux[0] ? !ClkIn : ClkIn) : (ClkMux[0] ? 1'b1 : 1'b0); | |
wire ClkEnMuxOut = ClkEnMux[1] ? (ClkEnMux[0] ? !ClkEn : ClkEn) : (ClkEnMux[0] ? 1'b1 : 1'b0); | |
alta_clkenctrl_rst inst(.ClkIn(ClkMuxOut), .ClkEn(ClkEnMuxOut), .Rst(1'b0), .ClkOut(ClkOut)); | |
endmodule | |
module alta_asyncctrl ( | |
input Din, | |
output Dout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter AsyncCtrlMux = 2'b10; | |
assign Dout = AsyncCtrlMux[1] ? (AsyncCtrlMux[0] ? !Din : Din) : (AsyncCtrlMux[0] ? 1'b1 : 1'b0); | |
endmodule | |
module alta_syncctrl ( | |
input Din, | |
output Dout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter SyncCtrlMux = 2'b10; | |
assign Dout = SyncCtrlMux[1] ? (SyncCtrlMux[0] ? !Din : Din) : (SyncCtrlMux[0] ? 1'b1 : 1'b0); | |
endmodule | |
module alta_io_gclk ( | |
input inclk, | |
output outclk | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
buf(outclk, inclk); | |
endmodule | |
module alta_gclksel ( | |
input [3:0] clkin, | |
input [1:0] select, | |
output clkout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
assign clkout = clkin[select]; | |
endmodule | |
module alta_gclkgen ( | |
input clkin, ena, | |
output clkout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter ENA_REG_MODE = 1'b0; | |
alta_dff inst(.Din(ena), .Clk(!clkin), .AsyncReset(1'b0), .Q(ena_reg)); | |
assign clkout = clkin & (ENA_REG_MODE ? ena_reg : ena); | |
endmodule | |
module alta_gclkgen0 ( | |
input clkin, ena, | |
output clkout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
alta_gclkgen inst(.clkin(clkin), .ena(ena), .clkout(clkout)); | |
endmodule | |
module alta_gclkgen2 ( | |
input clkin, ena, mode, | |
output clkout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter PLLOUTP_EN = 1'b0; | |
parameter PLLOUTN_EN = 1'b0; | |
alta_dff inst0(.Din(ena ), .Clk(!clkin), .AsyncReset(1'b0), .Q(ena_int)); | |
alta_dff inst1(.Din(ena_int), .Clk(!clkin), .AsyncReset(1'b0), .Q(ena_reg)); | |
assign clkout = clkin & (mode ? ena_reg : ena_int); | |
endmodule | |
module alta_io ( | |
inout padio, | |
input datain, oe, | |
output combout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter PRG_DELAYB = 1'b0; | |
parameter RX_SEL = 1'b0; | |
parameter PDCNTL = 2'b11; | |
parameter NDCNTL = 2'b11; | |
parameter PRG_SLR = 1'b0; | |
parameter CFG_KEEP = 2'b00; | |
parameter PU = 4'b1000; | |
parameter LVDS_OUT = 1'b0; | |
reg bus_keep, pull_up, pull_down; | |
reg open_drain, open_drain_p; | |
reg output_drv; | |
reg trigate_in, last_value, hold_value; | |
initial last_value = 1'b0; | |
always @(datain or oe or padio or CFG_KEEP or PDCNTL or NDCNTL) | |
begin | |
bus_keep = (CFG_KEEP[1:0] == 2'b11); | |
pull_up = (CFG_KEEP[1:0] == 2'b10); | |
pull_down = (CFG_KEEP[1:0] == 2'b01); | |
open_drain = (|PDCNTL == 1'b0 && |NDCNTL == 1'b1); // includes 0001, 0010, 0011 | |
open_drain_p = (|PDCNTL == 1'b1 && |NDCNTL == 1'b0); // includes 0100, 1000, 1100 | |
output_drv = (|PDCNTL == 1'b1 || |NDCNTL == 1'b1 || LVDS_OUT == 1'b1); // any output drive capability | |
if (output_drv) | |
begin | |
if (!open_drain && !open_drain_p) | |
trigate_in = datain; | |
else if (open_drain && datain == 1'b0) | |
trigate_in = 1'b0; | |
else if (open_drain_p && datain == 1'b1) | |
trigate_in = 1'b1; | |
else | |
trigate_in = 1'bz; | |
end | |
else // no output drive capability | |
trigate_in = 1'bz; | |
if (padio == 1'b0 || padio == 1'b1) | |
last_value = padio; | |
hold_value = (bus_keep ? last_value : (pull_up ? 1'b1 : (pull_down ? 1'b0 : 1'bz))); | |
end | |
cmos pad (padio , trigate_in, oe , ~oe); | |
cmos in (combout, last_value, 1'b1, 1'b0); | |
rcmos hold1(padio , hold_value, 1'b1, 1'b0); | |
rcmos hold2(combout, hold_value, 1'b1, 1'b0); | |
bufif1 (weak1, weak0) pu(padio, 1'b1, |PU); | |
endmodule | |
module alta_rio ( | |
input datain, oe, outclk, outclkena, inclk, inclkena, areset, sreset, | |
output combout, regout, | |
inout padio | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter IN_ASYNC_MODE = 1'b0; // 0: Reset, 1: Preset | |
parameter IN_SYNC_MODE = 1'b0; // 0: Reset, 1: Preset | |
parameter IN_POWERUP = 1'b0; // Power up value | |
parameter OUT_REG_MODE = 1'b0; // 0: Not registered, 1: Registered | |
parameter OUT_ASYNC_MODE = 1'b0; | |
parameter OUT_SYNC_MODE = 1'b0; | |
parameter OUT_POWERUP = 1'b0; | |
parameter OE_REG_MODE = 1'b0; | |
parameter OE_ASYNC_MODE = 1'b0; | |
parameter OE_SYNC_MODE = 1'b0; | |
parameter OE_POWERUP = 1'b0; | |
parameter CFG_TRI_INPUT = 1'b0; | |
parameter CFG_INPUT_EN = 1'b0; | |
parameter CFG_PULL_UP = 1'b0; | |
parameter CFG_SLR = 1'b0; | |
parameter CFG_OPEN_DRAIN = 1'b0; | |
parameter CFG_PDRCTRL = 4'b0010; | |
parameter CFG_KEEP = 2'b00; | |
parameter CFG_LVDS_OUT_EN = 1'b0; | |
parameter CFG_LVDS_SEL_CUA = 2'b00; | |
parameter CFG_LVDS_IREF = 10'b0000000000; | |
parameter CFG_LVDS_IN_EN = 1'b0; | |
parameter DPCLK_DELAY = 4'b0000; | |
parameter OUT_DELAY = 1'b0; | |
parameter IN_DATA_DELAY = 3'b000; | |
parameter IN_REG_DELAY = 3'b000; | |
wire paddatain, paddataout, padoe; | |
wire in_reg, out_reg, oe_reg; | |
// Input | |
wire input_data = sreset ? IN_SYNC_MODE : paddataout; | |
alta_srff #(IN_POWERUP) reg_in(.Din(input_data), .Clk(inclk), .ClkEn(inclkena), .AsyncReset(areset && !IN_ASYNC_MODE), .AsyncPreset(areset && IN_ASYNC_MODE), .Q(in_reg)); | |
assign regout = in_reg; | |
assign combout = paddataout; | |
// Output | |
wire output_data = sreset ? OUT_SYNC_MODE : datain; | |
alta_srff #(OUT_POWERUP) reg_out(.Din(output_data), .Clk(outclk), .ClkEn(outclkena), .AsyncReset(areset && !OUT_ASYNC_MODE), .AsyncPreset(areset && OUT_ASYNC_MODE), .Q(out_reg)); | |
assign paddatain = OUT_REG_MODE ? out_reg : datain; | |
// Output enable | |
wire oe_data = sreset ? OE_SYNC_MODE : oe; | |
alta_srff #(OE_POWERUP) reg_oe(.Din(oe_data), .Clk(outclk), .ClkEn(outclkena), .AsyncReset(areset && !OE_ASYNC_MODE), .AsyncPreset(areset && OE_ASYNC_MODE), .Q(oe_reg)); | |
assign padoe = OE_REG_MODE ? oe_reg : oe; | |
alta_io io_inst (.datain(paddatain), .oe(padoe), .combout(paddataout), .padio(padio)); | |
defparam io_inst.PU = CFG_PULL_UP ? 4'b1000 : 4'b0000; | |
defparam io_inst.CFG_KEEP = CFG_KEEP; | |
defparam io_inst.PDCNTL = CFG_OPEN_DRAIN ? 2'b00 : CFG_PDRCTRL; | |
defparam io_inst.NDCNTL = CFG_PDRCTRL; | |
defparam io_inst.LVDS_OUT = CFG_LVDS_OUT_EN; | |
endmodule | |
module alta_srff #(parameter INIT_VAL = 1'b0) ( | |
input Din, Clk, ClkEn, AsyncReset, AsyncPreset, | |
output reg Q | |
); | |
always @ (posedge Clk or posedge AsyncReset or posedge AsyncPreset) begin | |
if (AsyncReset == 1'b1) | |
Q <= 1'b0; | |
else if (AsyncPreset == 1'b1) | |
Q <= 1'b1; | |
else if (ClkEn == 1'b1) | |
Q <= Din; | |
end | |
`ifdef ALTA_SIM | |
initial Q = INIT_VAL; | |
always @ (AsyncReset or AsyncPreset) begin | |
if (!AsyncReset && AsyncPreset) | |
force Q = 1'b1; | |
else | |
release Q; | |
end | |
`endif | |
endmodule | |
module alta_dff #(parameter INIT_VAL = 1'b0) ( | |
input Din, Clk, AsyncReset, | |
output Q | |
); | |
alta_srff #(INIT_VAL) inst (.Din(Din), .Clk(Clk), .ClkEn(1'b1), .AsyncReset(AsyncReset), .AsyncPreset(1'b0), .Q(Q)); | |
endmodule | |
module alta_ufm_gddd(input in, output out); | |
assign out = in; | |
endmodule | |
module alta_dff_stall #(parameter INIT_VAL = 1'b0) ( | |
input Din, Clk, AsyncReset, Stall, | |
output Q | |
); | |
alta_dff #(INIT_VAL) inst (.Din(Stall ? Q : Din), .Clk(Clk), .AsyncReset(AsyncReset), .Q(Q)); | |
endmodule | |
module alta_srlat #(parameter INIT_VAL = 1'b0) ( | |
input Din, Clk, AsyncReset, AsyncPreset, | |
output reg Q | |
); | |
`ifdef ALTA_SIM | |
initial Q = INIT_VAL; | |
`endif | |
always @ (Din or Clk or AsyncReset or AsyncPreset) begin | |
if (AsyncPreset) begin | |
Q <= 1'b1; | |
end else if (AsyncReset) begin | |
Q <= 1'b0; | |
end else if (Clk) begin | |
Q <= Din; | |
end | |
end | |
endmodule | |
module alta_dio ( | |
input datain, datainh, oe, outclk, outclkena, inclk, inclkena, areset, sreset, | |
output combout, regout, | |
inout padio | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter IN_ASYNC_MODE = 1'b0; // 0: Reset, 1: Preset | |
parameter IN_SYNC_MODE = 1'b0; // 0: Reset, 1: Preset | |
parameter IN_POWERUP = 1'b0; // Power up value | |
parameter IN_ASYNC_DISABLE = 1'b0; // 1: input async reset disabled | |
parameter IN_SYNC_DISABLE = 1'b0; // 1: input sync reset disabled | |
parameter OUT_REG_MODE = 1'b0; // 0: Not registered, 1: Registered | |
parameter OUT_ASYNC_MODE = 1'b0; | |
parameter OUT_SYNC_MODE = 1'b0; | |
parameter OUT_POWERUP = 1'b0; | |
parameter OUT_CLKEN_DISABLE = 1'b0; // 1: output clken disabled | |
parameter OUT_ASYNC_DISABLE = 1'b0; | |
parameter OUT_SYNC_DISABLE = 1'b0; | |
parameter OUT_DDIO = 1'b0; | |
parameter OE_REG_MODE = 1'b0; | |
parameter OE_ASYNC_MODE = 1'b0; | |
parameter OE_SYNC_MODE = 1'b0; | |
parameter OE_POWERUP = 1'b0; | |
parameter OE_CLKEN_DISABLE = 1'b0; // 1: output enable clken disabled | |
parameter OE_ASYNC_DISABLE = 1'b0; | |
parameter OE_SYNC_DISABLE = 1'b0; | |
parameter OE_DDIO = 1'b0; | |
parameter CFG_TRI_INPUT = 1'b0; | |
parameter CFG_PULL_UP = 1'b0; | |
parameter CFG_OPEN_DRAIN = 1'b0; | |
parameter CFG_ROCT_CAL_EN = 1'b0; | |
parameter CFG_PDRV = 7'b0010000; | |
parameter CFG_NDRV = 7'b0010000; | |
parameter CFG_KEEP = 2'b0; | |
parameter CFG_LVDS_OUT_EN = 1'b0; | |
parameter CFG_LVDS_SEL_CUA = 3'b0; | |
parameter CFG_LVDS_IREF = 10'b0110000000; | |
parameter CFG_LVDS_IN_EN = 1'b0; | |
parameter CFG_SSTL_OUT_EN = 1'b0; | |
parameter CFG_SSTL_INPUT_EN = 1'b0; | |
parameter CFG_SSTL_SEL_CUA = 3'b0; | |
parameter CFG_OSCDIV = 2'b0; | |
parameter CFG_ROCTUSR = 1'b0; | |
parameter CFG_SEL_CUA = 1'b0; | |
parameter CFG_ROCT_EN = 1'b0; | |
parameter DPCLK_DELAY = 4'b0000; | |
parameter OUT_DELAY = 1'b0; | |
parameter IN_DATA_DELAY = 3'b000; | |
parameter IN_REG_DELAY = 3'b000; | |
wire paddatain, paddataout, padoe; | |
wire in_reg, out_reg, oe_reg; | |
// Input | |
wire in_data = (sreset & !IN_SYNC_DISABLE) ? IN_SYNC_MODE : paddataout; | |
wire in_asyncreset = areset & !IN_ASYNC_DISABLE & !IN_ASYNC_MODE; | |
wire in_asyncpreset = areset & !IN_ASYNC_DISABLE & IN_ASYNC_MODE; | |
alta_srff #(IN_POWERUP) reg_in(.Din(in_data), .Clk(inclk), .ClkEn(inclkena), .AsyncReset(in_asyncreset), .AsyncPreset(in_asyncpreset), .Q(in_reg)); | |
assign regout = in_reg; | |
assign combout = paddataout; | |
// Output | |
wire out_data_h = (sreset & !OUT_SYNC_DISABLE) ? OUT_SYNC_MODE : datainh; | |
wire out_data_l = (sreset & !OUT_SYNC_DISABLE) ? OUT_SYNC_MODE : datain; | |
wire out_clken = outclkena | OUT_CLKEN_DISABLE; | |
wire out_asyncreset = areset & !OUT_ASYNC_DISABLE & !OUT_ASYNC_MODE; | |
wire out_asyncpreset = areset & !OUT_ASYNC_DISABLE & OUT_ASYNC_MODE; | |
alta_srlat data_h_inst(.Din(out_data_h), .Clk(!outclk | !out_clken), .AsyncReset(out_asyncreset), .AsyncPreset(out_asyncpreset), .Q(outreg_h)); | |
alta_srff #(OUT_POWERUP) data_l_inst(.Din(out_data_l), .Clk(outclk), .ClkEn(out_clken), .AsyncReset(out_asyncreset), .AsyncPreset(out_asyncpreset), .Q(outreg_l)); | |
assign paddatain = !OUT_REG_MODE ? datain : !OUT_DDIO ? outreg_l : outclk ? outreg_h : outreg_l; | |
// Output enable | |
wire oe_data_h = (sreset & !OE_SYNC_DISABLE) ? OE_SYNC_MODE : oe; | |
wire oe_clken = outclkena | OE_CLKEN_DISABLE; | |
wire oe_asyncreset = areset & !OE_ASYNC_DISABLE & !OE_ASYNC_MODE; | |
wire oe_asyncpreset = areset & !OE_ASYNC_DISABLE & OE_ASYNC_MODE; | |
alta_srff #(OE_POWERUP) oe_h_inst(.Din(oe_data_h), .Clk( outclk), .ClkEn(oe_clken), .AsyncReset(oe_asyncreset), .AsyncPreset(oe_asyncpreset), .Q(oe_reg_h)); | |
alta_srff #(OE_POWERUP) oe_l_inst(.Din(oe_reg_h), .Clk(!outclk), .ClkEn(oe_clken), .AsyncReset(oe_asyncreset), .AsyncPreset(oe_asyncpreset), .Q(oe_reg_l)); | |
assign padoe = !OE_REG_MODE ? oe : !OE_DDIO ? oe_reg_h : !oe_reg_h ? oe_reg_h : oe_reg_l; | |
alta_io io_inst (.datain(paddatain), .oe(padoe), .combout(paddataout), .padio(padio)); | |
defparam io_inst.PU = CFG_PULL_UP ? 4'b1000 : 4'b0000; | |
defparam io_inst.CFG_KEEP = CFG_KEEP; | |
defparam io_inst.PDCNTL = CFG_OPEN_DRAIN ? 2'b00 : |CFG_PDRV ? 2'b11 : 2'b00; | |
defparam io_inst.NDCNTL = |CFG_NDRV ? 2'b11 : 2'b00; | |
defparam io_inst.LVDS_OUT = CFG_LVDS_OUT_EN; | |
endmodule | |
module alta_ufms ( | |
input tri1 i_ufm_set, | |
input i_osc_ena, | |
input i_ufm_flash_csn, | |
input i_ufm_flash_sclk, | |
input i_ufm_flash_sdi, | |
output o_osc, | |
output o_ufm_flash_sdo | |
); | |
`ifdef ALTA_SIM | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
alta_ufms_sim ufm0 ( | |
.osc_ena(i_osc_ena ), | |
.cs (i_ufm_flash_csn ), | |
.sclk (i_ufm_flash_sclk & i_ufm_set),// Shut down clk when i_ufm_set is low | |
.si (i_ufm_flash_sdi ), | |
.osc (o_osc ), | |
.so (o_ufm_flash_sdo ) | |
); | |
defparam ufm0.TPP_TIME = 10000; | |
`endif | |
endmodule | |
`timescale 1ns/10ps | |
module alta_ufms_sim (input sclk , | |
input si , | |
input cs , | |
output so , | |
output osc , | |
input osc_ena | |
); | |
parameter TPP_TIME = 700000; // page program cycle time (0.7ms) | |
parameter TSE_TIME = 100000000; // sector erase cycle time (100ms) | |
parameter TCE_TIME = 300000000; // sector erase cycle time (100ms) | |
parameter osc_sim_setting = 180; // default osc frequency to 5.56MHz | |
parameter T_HALF_PERIOD = osc_sim_setting/2; | |
`ifndef ALTA_SIM | |
alta_ufms ufm0 ( | |
.i_ufm_set ( ), | |
.i_osc_ena (osc_ena), | |
.i_ufm_flash_csn (cs ), | |
.i_ufm_flash_sclk(sclk ), | |
.i_ufm_flash_sdi (si ), | |
.o_osc (osc ), | |
.o_ufm_flash_sdo (so ) | |
); | |
`else | |
reg osc_reg; | |
assign osc = osc_reg; | |
parameter CMD_RDDATA = 8'h03 , | |
CMD_PAGE_PROGRAM = 8'h02 , | |
CMD_SECTOR_ERASE = 8'h20 , | |
CMD_CHIP_ERASE = 8'h52 , | |
CMD_WRITE_ENABLE = 8'h06 , | |
CMD_READ_STATUS_REG = 8'h05 ; | |
parameter address_width = 16; | |
parameter num_bytes = 1 << address_width; | |
parameter sector_range = 1<<(address_width - 4); | |
reg [7:0] mem [(1<<address_width -1)-1:0] ; | |
reg [7:0] data_reg ; | |
reg [7:0] data_shift_reg ; | |
reg [2:0] cnt_flash_bit ; | |
reg [7:0] cmd_reg ; | |
reg [23:0] addr_reg ; | |
reg [7:0] dataout ; | |
reg program_pulse ; | |
reg erase_pulse ; | |
reg wren_pusle ; | |
reg program_pulse_d1 ; | |
reg program_pulse_d2 ; | |
reg erase_pulse_d1 ; | |
reg erase_pulse_d2 ; | |
reg first_warning ; | |
reg [5:0]cnt_cmd_addr ; | |
reg [2:0]cnt_pp_bit ; | |
reg ufm_sdo_valid ; | |
reg sdo_valid_tmp ; | |
reg [23:0] erase_addr ; | |
reg erase_reg ; | |
integer i; | |
initial | |
begin | |
first_warning = 1; | |
program_pulse = 0; | |
erase_pulse = 0; | |
erase_addr = 0; | |
osc_reg = 1; | |
for (i=0; i<num_bytes; i=i+1) | |
mem[i] = 8'hFF; | |
end | |
always@(negedge sclk) | |
begin | |
program_pulse_d1 <= program_pulse; | |
program_pulse_d2 <= program_pulse_d1; | |
erase_pulse_d1 <= erase_pulse; | |
erase_pulse_d2 <= erase_pulse_d1; | |
end | |
always@( * ) | |
begin | |
if((cmd_reg == CMD_PAGE_PROGRAM) && (cnt_cmd_addr == 6'h18) && (cnt_flash_bit == 3'b111)) | |
begin | |
program_pulse = 1; | |
$display("%t: NOTE : Page program cycle is started",$realtime); | |
end | |
else if(cs && (cmd_reg == CMD_PAGE_PROGRAM)) | |
begin | |
program_pulse = #TPP_TIME 0; | |
$display("%t: NOTE : Page program cycle is finished",$realtime); | |
end | |
end | |
always@( * ) | |
begin | |
if(((cmd_reg == CMD_SECTOR_ERASE) || (cmd_reg == CMD_CHIP_ERASE))&& (cnt_cmd_addr == 6'h00) && (cnt_flash_bit == 3'b111)) | |
erase_reg = 1; | |
else | |
erase_reg = 0; | |
end | |
always@(posedge erase_reg) | |
begin | |
if(cmd_reg == CMD_SECTOR_ERASE) | |
begin | |
erase_pulse = 1; | |
#TSE_TIME; | |
erase_pulse = 0; | |
end | |
else if(cmd_reg == CMD_CHIP_ERASE) | |
begin | |
erase_pulse = 1; | |
#TCE_TIME; | |
erase_pulse = 0; | |
end | |
end | |
always@(negedge sclk) | |
begin | |
if(cmd_reg == CMD_WRITE_ENABLE ) | |
begin | |
wren_pusle = 1; | |
$display("%t: NOTE : Flash write enable is set",$realtime); | |
end | |
else if((!program_pulse_d1 && program_pulse_d2) || (!erase_pulse_d1 && erase_pulse_d2)) | |
begin | |
wren_pusle = 0; | |
$display("%t: NOTE : Flash write enable is reset",$realtime); | |
end | |
end | |
always@(negedge sclk or posedge cs) | |
begin | |
if(cs) | |
cnt_flash_bit <= 3'b111; | |
else if(!cs) | |
cnt_flash_bit <= cnt_flash_bit - 3'b001; | |
end | |
always@(negedge sclk or posedge cs) | |
begin | |
if(cs) | |
cnt_cmd_addr <= 6'h20 ; | |
else if(!cs && |cnt_cmd_addr) | |
cnt_cmd_addr <= cnt_cmd_addr - 6'b000001 ; | |
end | |
always@(negedge sclk or posedge cs) | |
begin | |
if(cs) | |
addr_reg <= 0 ; | |
else if((cnt_cmd_addr == 6'h00) && (cnt_flash_bit == 3'b000)) | |
addr_reg <= addr_reg + 1; | |
else if((cnt_cmd_addr >= 6'h01 && cnt_cmd_addr <= 6'h18) && cmd_reg != CMD_READ_STATUS_REG) | |
addr_reg <= {addr_reg[22:0],si}; | |
end | |
always@(posedge sclk or posedge cs) | |
begin | |
if(cs) | |
cmd_reg <= 0 ; | |
else if(cnt_cmd_addr >= 6'h19 && cnt_cmd_addr <= 6'h20) | |
cmd_reg <= {cmd_reg[6:0],si} ; | |
end | |
always@(negedge sclk) | |
begin | |
if((cnt_cmd_addr == 6'h01) && (cmd_reg == CMD_SECTOR_ERASE)) | |
erase_addr <= addr_reg ; | |
end | |
always@(cs or cmd_reg or cnt_cmd_addr or addr_reg or mem[addr_reg] or program_pulse or erase_pulse) | |
begin | |
if(cs) | |
dataout = 0; | |
else if((cmd_reg == CMD_RDDATA) && (cnt_cmd_addr == 6'h00)) | |
dataout = mem[addr_reg]; | |
else if((cmd_reg == CMD_READ_STATUS_REG) && (program_pulse || erase_pulse)) | |
dataout = 8'h01; | |
else | |
dataout = 0; | |
end | |
assign so = ufm_sdo_valid ? dataout[cnt_flash_bit] : 1'b0; | |
always@(posedge sclk or posedge cs) | |
begin | |
if(cs) | |
sdo_valid_tmp <= 0; | |
else if((cmd_reg == 8'h03) && (cnt_cmd_addr == 6'h01)) | |
sdo_valid_tmp <= 1; | |
else if((cmd_reg == 8'h02) && (cnt_cmd_addr == 6'h19) && si ) | |
sdo_valid_tmp <= 1; | |
end | |
always@(negedge sclk or posedge cs) | |
begin | |
if(cs) | |
ufm_sdo_valid <= 0; | |
else | |
ufm_sdo_valid <= sdo_valid_tmp; | |
end | |
always@(posedge sclk or posedge cs) | |
begin | |
if(cs) | |
cnt_pp_bit <= 3'b111; | |
else if(!cs) | |
cnt_pp_bit <= cnt_pp_bit - 3'b001; | |
end | |
always@(posedge sclk or posedge cs) | |
begin | |
if(cs) | |
data_shift_reg <= 0; | |
else if((cmd_reg == CMD_PAGE_PROGRAM) && wren_pusle && (cnt_cmd_addr == 6'h00)) | |
data_shift_reg[cnt_pp_bit] <= si ; | |
end | |
always@(negedge sclk) | |
begin | |
if((cmd_reg == CMD_PAGE_PROGRAM) && wren_pusle && (cnt_cmd_addr == 6'h00) && (cnt_pp_bit == 3'b111)) | |
begin | |
mem[addr_reg] <= data_shift_reg & mem[addr_reg];// The write operation is the logical "AND" in UFM | |
end | |
end | |
// Produce oscillation clock to UFM | |
always @(osc_reg or osc_ena) | |
begin | |
if (osc_ena === 'b1) | |
begin | |
if (first_warning == 1) | |
begin | |
$display("Info : UFM oscillator can operate at any frequency between 3.33MHz to 5.56Mhz."); | |
$display ("Time: %0t Instance: %m", $time); | |
first_warning = 0; | |
end | |
if (osc_reg === 'b0 || osc_reg === 'b1) | |
osc_reg <= #T_HALF_PERIOD ~osc_reg; | |
else | |
osc_reg <= #T_HALF_PERIOD 0; | |
end | |
else | |
begin | |
osc_reg <= #T_HALF_PERIOD 1; | |
end | |
end | |
integer k = 0; | |
always @(posedge erase_pulse) | |
begin | |
if(cmd_reg == CMD_SECTOR_ERASE) | |
begin | |
if(erase_addr >= 0 && erase_addr < sector_range) | |
begin | |
$display("%t: NOTE : Sector0 erase cycle has begun",$realtime); | |
for (k=0; k<sector_range; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector0 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range && erase_addr < sector_range*2)) | |
begin | |
$display("%t: NOTE : Sector1 erase cycle has begun",$realtime); | |
for (k=sector_range; k<sector_range*2; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector1 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range*2 && erase_addr < sector_range*3)) | |
begin | |
$display("%t: NOTE : Sector2 erase cycle has begun",$realtime); | |
for (k=sector_range*2; k<sector_range*3; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector2 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range*3 && erase_addr < sector_range*4)) | |
begin | |
$display("%t: NOTE : Sector3 erase cycle has begun",$realtime); | |
for (k=sector_range*3; k<sector_range*4; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector3 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range*4 && erase_addr < sector_range*5)) | |
begin | |
$display("%t: NOTE : Sector4 erase cycle has begun",$realtime); | |
for (k=sector_range*4; k<sector_range*5; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector4 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range*5 && erase_addr < sector_range*6)) | |
begin | |
$display("%t: NOTE : Sector5 erase cycle has begun",$realtime); | |
for (k=sector_range*5; k<sector_range*6; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector5 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range*6 && erase_addr < sector_range*7)) | |
begin | |
$display("%t: NOTE : Sector6 erase cycle has begun",$realtime); | |
for (k=sector_range*6; k<sector_range*7; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector6 erase cycle is finished",$realtime); | |
end | |
else if((erase_addr >= sector_range*7 && erase_addr < sector_range*8)) | |
begin | |
$display("%t: NOTE : Sector7 erase cycle has begun",$realtime); | |
for (k=sector_range*7; k<sector_range*8; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : Sector7 erase cycle is finished",$realtime); | |
end | |
end | |
else if(cmd_reg == CMD_CHIP_ERASE) | |
begin | |
$display("%t: NOTE : CHIP erase cycle is begun",$realtime); | |
for(k=0;k<sector_range*8; k=k+1) | |
begin | |
mem[k] <= 8'hff; // Data in UFM is erased to all 1's | |
end | |
$display("%t: NOTE : CHIP erase cycle is finished",$realtime); | |
end | |
end | |
`endif | |
endmodule | |
`timescale 1ns/10ps | |
module alta_pll ( | |
input clkin, clkfb, | |
input pllen, resetn, pfden, | |
output clkout0, clkout1, | |
output lock | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter CLKIN_DIV = 6'h1; | |
parameter CLKFB_DIV = 6'h1; | |
parameter CLKOUT0_DIV = 6'h1; | |
parameter CLKOUT1_DIV = 6'h1; | |
parameter CLKOUT0_DEL = 6'h0; | |
parameter CLKOUT1_DEL = 6'h0; | |
parameter CLKOUT0_PHASE = 3'h0; | |
parameter CLKOUT1_PHASE = 3'h0; | |
parameter FEEDBACK_CLOCK = 1'b0; | |
parameter FEEDBACK_MODE = 1'b1; | |
parameter CLKOUT0_EN = 1'h1; | |
parameter CLKOUT1_EN = 1'h1; | |
parameter CLKIN_FREQ = 10.0; | |
parameter CLKFB_FREQ = 10.0; | |
parameter CLKOUT0_FREQ = 10.0; | |
parameter CLKOUT1_FREQ = 10.0; | |
`ifdef ALTA_SIM | |
alta_pll_sim #( | |
.NUM_CLKOUTS (2), | |
.CLKIN_DIV_BITS (6), | |
.CLKFB_DIV_BITS (6), | |
.CLKOUT_DIV_BITS (6), | |
.CLKOUT_DEL_BITS (6), | |
.CLKOUT_PHASE_BITS(3) | |
) sim_inst ( | |
.clkin (clkin ), | |
.clkfb (clkfb ), | |
.pllen (pllen ), | |
.resetn (resetn ), | |
.pfden (pfden ), | |
.clkout ({clkout1 , clkout0 } ), | |
.clkouten ({CLKOUT1_EN, CLKOUT0_EN} ), | |
.lock (lock ), | |
.FEEDBACK_CLOCK(FEEDBACK_CLOCK ), | |
.FEEDBACK_MODE (FEEDBACK_MODE ), | |
.CLKIN_DIV (CLKIN_DIV ), | |
.CLKFB_DIV (CLKFB_DIV ), | |
.CLKDIV_EN (2'b11 ), | |
.CLKOUT_DIVS ({CLKOUT1_DIV , CLKOUT0_DIV }), | |
.CLKOUT_DELS ({CLKOUT1_DEL , CLKOUT0_DEL }), | |
.CLKOUT_PHASES ({CLKOUT1_PHASE, CLKOUT0_PHASE}) | |
); | |
`else | |
assign clkout0 = clkin; | |
assign clkout1 = clkin; | |
assign lock = pllen & resetn & pfden & clkfb; | |
`endif | |
endmodule | |
module alta_pllx ( | |
input clkin, clkfb, pllen, resetn, | |
input clkout0en, clkout1en, clkout2en, clkout3en, | |
output clkout0, clkout1, clkout2, clkout3, lock | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter CLKIN_DIV = 6'd0; | |
parameter CLKFB_DIV = 6'd0; | |
parameter CLKDIV0_EN = 1'b0; | |
parameter CLKDIV1_EN = 1'b0; | |
parameter CLKDIV2_EN = 1'b0; | |
parameter CLKDIV3_EN = 1'b0; | |
parameter CLKOUT0_DIV = 6'd0; | |
parameter CLKOUT1_DIV = 6'd0; | |
parameter CLKOUT2_DIV = 6'd0; | |
parameter CLKOUT3_DIV = 6'd0; | |
parameter CLKOUT0_DEL = 6'd0; | |
parameter CLKOUT1_DEL = 6'd0; | |
parameter CLKOUT2_DEL = 6'd0; | |
parameter CLKOUT3_DEL = 6'd0; | |
parameter CLKOUT0_PHASE = 3'd0; | |
parameter CLKOUT1_PHASE = 3'd0; | |
parameter CLKOUT2_PHASE = 3'd0; | |
parameter CLKOUT3_PHASE = 3'd0; | |
parameter FEEDBACK_MODE = 1'b1; | |
parameter FEEDBACK_CLOCK = 2'b00; | |
parameter CLKIN_FREQ = 60.000; | |
parameter CLKFB_FREQ = 20.000; | |
parameter CLKOUT0_FREQ = -1.000; | |
parameter CLKOUT1_FREQ = 50.000; | |
parameter CLKOUT2_FREQ = 80.000; | |
parameter CLKOUT3_FREQ = 100.000; | |
`ifdef ALTA_SIM | |
alta_pll_sim #( | |
.NUM_CLKOUTS (4), | |
.CLKIN_DIV_BITS (6), | |
.CLKFB_DIV_BITS (6), | |
.CLKOUT_DIV_BITS (6), | |
.CLKOUT_DEL_BITS (6), | |
.CLKOUT_PHASE_BITS(3) | |
) sim_inst ( | |
.clkin (clkin ), | |
.clkfb (clkfb ), | |
.pllen (pllen ), | |
.resetn (resetn ), | |
.pfden (1'b1 ), | |
.clkout ({clkout3 , clkout2 , clkout1 , clkout0 } ), | |
.clkouten ({clkout3en, clkout2en, clkout1en, clkout0en} ), | |
.lock (lock ), | |
.FEEDBACK_CLOCK(FEEDBACK_CLOCK ), | |
.FEEDBACK_MODE (FEEDBACK_MODE ), | |
.CLKIN_DIV (CLKIN_DIV ), | |
.CLKFB_DIV (CLKFB_DIV ), | |
.CLKDIV_EN ({CLKDIV3_EN , CLKDIV2_EN , CLKDIV1_EN , CLKDIV0_EN }), | |
.CLKOUT_DIVS ({CLKOUT3_DIV , CLKOUT2_DIV , CLKOUT1_DIV , CLKOUT0_DIV }), | |
.CLKOUT_DELS ({CLKOUT3_DEL , CLKOUT2_DEL , CLKOUT1_DEL , CLKOUT0_DEL }), | |
.CLKOUT_PHASES ({CLKOUT3_PHASE, CLKOUT2_PHASE, CLKOUT1_PHASE, CLKOUT0_PHASE}) | |
); | |
`else | |
assign clkout0 = clkout0en & clkin; | |
assign clkout1 = clkout1en & clkin; | |
assign clkout2 = clkout2en & clkin; | |
assign clkout3 = clkout3en & clkin; | |
assign lock = pllen & resetn & clkfb; | |
`endif | |
endmodule | |
`ifdef ALTA_SIM | |
`timescale `PLL_RESOLUTION | |
module pll_clk_div #( | |
parameter DIV_BITS = 6, | |
DEL_BITS = 6) ( | |
input clkin, rst, ena, | |
output clkout, | |
input CLKDIV_EN, | |
input [DIV_BITS-1:0] CLK_DIV, | |
input [DEL_BITS-1:0] CLK_DEL | |
); | |
reg clk = 1'b0; | |
reg [DIV_BITS-1:0] divcnt = 0; | |
reg [DEL_BITS-1:0] dlycnt = 0; | |
reg pos_level, neg_level; | |
reg rst_sync1, rst_sync2; | |
reg divcnt_en; | |
wire [DIV_BITS:0] half_period = {1'b0, CLK_DIV[DIV_BITS-1:0]} + 1'b1; | |
initial begin | |
divcnt = {DIV_BITS{1'b0}}; | |
dlycnt = {DEL_BITS{1'b0}}; | |
pos_level = 1'b0; | |
neg_level = 1'b0; | |
rst_sync1 = 1'b0; | |
rst_sync2 = 1'b0; | |
divcnt_en = 1'b0; | |
end | |
always @(*) begin | |
if (CLK_DIV == {DIV_BITS{1'b0}}) begin | |
if (divcnt_en) | |
clk = clkin; | |
else | |
clk = 1'b0; | |
end else begin | |
if (CLK_DIV[0] == 1'b1) // Even divider | |
clk = pos_level; | |
else | |
clk = pos_level || neg_level; | |
end | |
end | |
reg clk_ena = 1'b0; | |
always @(*) begin | |
if (rst) begin | |
clk_ena <= 1'b0; | |
end else if (!clk) begin | |
clk_ena <= ena; | |
end | |
end | |
assign clkout = clk & clk_ena; | |
always @(posedge clkin or posedge rst) begin | |
if (rst) begin | |
rst_sync1 <= 1'b0; | |
rst_sync2 <= 1'b0; | |
end else if (CLKDIV_EN) begin | |
rst_sync1 <= 1'b1; | |
rst_sync2 <= rst_sync1; | |
end | |
end | |
always @(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
dlycnt <= {DEL_BITS{1'b0}}; | |
else if (!divcnt_en) | |
dlycnt <= dlycnt + 1'd1; | |
end | |
always @(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
divcnt_en <= 1'b0; | |
else if (CLK_DEL == {DEL_BITS{1'b0}}) | |
divcnt_en <= 1'b1; | |
else if (dlycnt == CLK_DEL) | |
divcnt_en <= 1'b1; | |
end | |
always @(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
divcnt <= {DIV_BITS{1'b0}}; | |
else if (!divcnt_en) | |
divcnt <= {DIV_BITS{1'b0}}; | |
else if (divcnt == CLK_DIV) | |
divcnt <= {DIV_BITS{1'b0}}; | |
else | |
divcnt <= divcnt + 1'd1; | |
end | |
always @(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
pos_level <= 1'b0; | |
else if (!divcnt_en) | |
pos_level <= 1'b0; | |
else if (divcnt == {DIV_BITS{1'b0}}) | |
pos_level <= 1'b1; | |
else if (divcnt == half_period[DIV_BITS:1]) | |
pos_level <= 1'b0; | |
end | |
always @(negedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
neg_level <= 1'b0; | |
else if (!divcnt_en) | |
neg_level <= 1'b0; | |
else | |
neg_level <= pos_level; | |
end | |
endmodule | |
`timescale `PLL_RESOLUTION | |
module alta_pll_core #( | |
parameter NUM_CLKOUTS = 4, | |
TOTAL_FBDIV_BITS = 12, | |
CLKOUT_PHASE_BITS = 3) ( | |
input pllen, pfden, | |
input pfd_clkin, pfd_clkfb, | |
output [NUM_CLKOUTS-1:0] vco_clkout, | |
output reg [(1 << CLKOUT_PHASE_BITS)-1:0] vco_taps, | |
output reg lock, | |
input [TOTAL_FBDIV_BITS-1:0] TOTAL_FBDIV, | |
input [CLKOUT_PHASE_BITS*NUM_CLKOUTS-1:0] CLKOUT_PHASES | |
); | |
localparam epsilon = 1.5; | |
realtime last_clkin_edge, next_clkin_edge; | |
realtime last_clkfb_edge, next_clkfb_edge; | |
realtime pfd_clkin_period, pfd_clkin_period0, pfd_clkin_period1, pfd_clkin_period2, pfd_clkfb_period; | |
realtime vco_clk_pulse, vco_clk_offset, fb_delay0, fb_delay1, fb_compensation; | |
real rounding_error; | |
integer vco_index; | |
reg pfd_clkin_valid, vco_clk_valid; | |
reg vco_clk, intfb_clk; | |
initial begin | |
reset; | |
end | |
always @(negedge pllen) begin | |
reset; | |
end | |
task reset; begin | |
last_clkin_edge = 0.0; | |
next_clkin_edge = 0.0; | |
pfd_clkin_period0 = 0.0; | |
pfd_clkin_period1 = 0.0; | |
pfd_clkin_period2 = 0.0; | |
pfd_clkin_period = 0.0; | |
last_clkfb_edge = 0.0; | |
next_clkfb_edge = 0.0; | |
pfd_clkfb_period = 0.0; | |
fb_delay0 = 0.0; | |
fb_delay1 = 0.0; | |
fb_compensation = 0.0; | |
rounding_error = 0.0; | |
vco_index = 0; | |
vco_clk_pulse = 5.0; | |
vco_clk_offset = 0.0; | |
pfd_clkin_valid = 1'b0; | |
vco_clk_valid = 1'b0; | |
vco_clk = 1'b1; | |
intfb_clk = 1'b1; | |
lock = 1'b0; | |
end | |
endtask | |
always @(posedge pfd_clkin or negedge pllen) begin | |
if (!pllen) begin | |
pfd_clkin_valid = 1'b0; | |
end else begin | |
last_clkin_edge = next_clkin_edge; | |
next_clkin_edge = $realtime; | |
if (last_clkin_edge > 0) begin | |
pfd_clkin_period = pfd_clkin_period2; | |
pfd_clkin_period2 = pfd_clkin_period1; | |
pfd_clkin_period1 = pfd_clkin_period0; | |
pfd_clkin_period0 = next_clkin_edge - last_clkin_edge; | |
end | |
if (pfd_clkin_period > 0 && is_equal(pfd_clkin_period , pfd_clkin_period0) | |
&& is_equal(pfd_clkin_period0, pfd_clkin_period1) | |
&& is_equal(pfd_clkin_period1, pfd_clkin_period2)) begin | |
pfd_clkin_valid = 1'b1; | |
if (TOTAL_FBDIV != 0) begin | |
vco_clk_pulse = round_number(pfd_clkin_period / TOTAL_FBDIV / 2); | |
rounding_error = (pfd_clkin_period - TOTAL_FBDIV * vco_clk_pulse * 2) / 2; | |
end | |
end else begin | |
pfd_clkin_valid = 1'b0; | |
end | |
end | |
end | |
always @(posedge pfd_clkfb or negedge pllen or negedge vco_clk_valid) begin | |
if (!pllen || !vco_clk_valid) begin | |
fb_delay0 = 0.0; | |
fb_delay1 = 0.0; | |
end else begin | |
last_clkfb_edge = next_clkfb_edge; | |
next_clkfb_edge = $realtime; | |
if (last_clkfb_edge > 0) begin | |
pfd_clkfb_period = next_clkfb_edge - last_clkfb_edge; | |
end | |
if (is_equal(pfd_clkin_period, pfd_clkfb_period)) begin | |
if (!lock) begin | |
fb_delay1 = fb_delay0; | |
fb_delay0 = last_clkin_edge - last_clkfb_edge; | |
if (fb_delay0 < -epsilon) begin | |
fb_delay0 = next_clkin_edge - last_clkfb_edge; | |
end | |
end | |
if (fb_delay0 > epsilon && fb_delay1 >= 0) begin | |
fb_compensation = fb_delay1; | |
while (fb_compensation > pfd_clkfb_period) begin | |
fb_compensation = fb_compensation - pfd_clkfb_period; | |
end | |
end | |
end | |
end | |
end | |
always @(negedge pfd_clkfb or negedge pllen or negedge lock) begin | |
if (!pllen || !lock) begin | |
vco_clk_offset = 0.0; | |
end else if (lock) begin | |
vco_clk_offset = next_clkin_edge - next_clkfb_edge; | |
end | |
end | |
always @(pfd_clkin or pfd_clkfb or negedge pllen) begin | |
if (!pllen) begin | |
lock <= 1'b0; | |
end else if ($realtime - next_clkfb_edge > 2 * pfd_clkfb_period) begin | |
lock <= 1'b0; | |
end else if ($realtime - next_clkin_edge > 2 * pfd_clkin_period) begin | |
lock <= 1'b0; | |
end else if (pfd_clkin_valid && vco_clk_valid && fb_delay0 < epsilon && is_equal(pfd_clkin_period, pfd_clkfb_period)) begin | |
lock <= 1'b1; | |
end else begin | |
lock <= 1'b0; | |
end | |
end | |
always @ (lock) begin | |
if (lock) begin | |
$display("PLL core %m is locked at: %t", $realtime); | |
end else if ($realtime > 0) begin | |
$display("PLL core %m is unlocked at: %t", $realtime); | |
end | |
end | |
always @(pfd_clkin or pfd_clkfb or negedge pllen) begin | |
if (!pllen) begin | |
vco_clk_valid <= 1'b0; | |
end else if (!lock) begin | |
vco_clk_valid <= pfd_clkin_valid; | |
end else if (!is_equal(pfd_clkin_period, pfd_clkfb_period)) begin | |
vco_clk_valid <= 1'b0; | |
end | |
end | |
real vco_shift, intfb_pulse; | |
always @(vco_clk_valid or intfb_clk) begin | |
if (!vco_clk_valid) begin | |
intfb_clk <= 1'b1; | |
vco_index = 0; | |
end else begin | |
vco_index = vco_index + 1; | |
vco_shift = 0.0; | |
if (vco_index >= TOTAL_FBDIV) begin | |
vco_index = 0; | |
vco_shift = rounding_error; | |
end | |
if (pfd_clkfb == 1'b0) begin | |
vco_shift = vco_shift + vco_clk_offset; | |
vco_clk_offset = 0; | |
end | |
if (pfden) begin | |
intfb_pulse = vco_clk_pulse + vco_shift; | |
if (intfb_pulse <= 0) begin | |
intfb_pulse = 0.1; | |
end | |
intfb_clk <= #intfb_pulse !intfb_clk; | |
end else begin | |
intfb_clk <= #1.5 !intfb_clk; | |
end | |
end | |
end | |
always @(intfb_clk) begin | |
vco_clk <= #(fb_compensation) intfb_clk; | |
end | |
generate | |
genvar v; | |
for (v = 0; v < (1 << CLKOUT_PHASE_BITS); v = v + 1) begin | |
always @ (vco_clk) begin | |
vco_taps[v] <= #(vco_clk_pulse * 2 * v / (1 << CLKOUT_PHASE_BITS)) vco_clk; | |
end | |
end | |
endgenerate | |
reg [CLKOUT_PHASE_BITS-1:0] CLKOUT_PHASES_VAL [NUM_CLKOUTS-1:0]; | |
generate | |
genvar i; | |
for (i = 0; i < NUM_CLKOUTS; i = i + 1) begin | |
always @(vco_taps[CLKOUT_PHASES[CLKOUT_PHASE_BITS * (i + 1) - 1-:CLKOUT_PHASE_BITS]]) begin | |
CLKOUT_PHASES_VAL[i] = #(vco_clk_pulse / (1 << CLKOUT_PHASE_BITS)) CLKOUT_PHASES[CLKOUT_PHASE_BITS * (i + 1) - 1-:CLKOUT_PHASE_BITS]; | |
end | |
assign vco_clkout[i] = vco_taps[CLKOUT_PHASES_VAL[i]]; | |
end | |
endgenerate | |
function is_equal(input real n1, input real n2); | |
begin | |
is_equal = (n1 < n2 + epsilon && n2 < n1 + epsilon); | |
end | |
endfunction | |
function real round_number(input real number); | |
begin | |
round_number = $rtoi(number * 100000.0) / 100000.0; // 100000 = 1ns / 10fs | |
end | |
endfunction | |
endmodule | |
`timescale `PLL_RESOLUTION | |
module alta_pll_sim #( | |
parameter NUM_CLKOUTS = 4, | |
CLKIN_DIV_BITS = 6, | |
CLKFB_DIV_BITS = 6, | |
CLKOUT_DIV_BITS = 6, | |
CLKOUT_DEL_BITS = 6, | |
CLKOUT_PHASE_BITS = 3) ( | |
input clkin, clkfb, | |
input pllen, resetn, pfden, | |
input [NUM_CLKOUTS-1:0] clkouten, | |
output [NUM_CLKOUTS-1:0] clkout, | |
output reg lock, | |
input [clogb2(NUM_CLKOUTS)-1:0] FEEDBACK_CLOCK, | |
input FEEDBACK_MODE, | |
input [CLKIN_DIV_BITS-1:0] CLKIN_DIV, | |
input [CLKFB_DIV_BITS-1:0] CLKFB_DIV, | |
input [NUM_CLKOUTS-1:0] CLKDIV_EN, | |
input [CLKOUT_DIV_BITS*NUM_CLKOUTS-1:0] CLKOUT_DIVS, | |
input [CLKOUT_DEL_BITS*NUM_CLKOUTS-1:0] CLKOUT_DELS, | |
input [CLKOUT_PHASE_BITS*NUM_CLKOUTS-1:0] CLKOUT_PHASES | |
); | |
wire [NUM_CLKOUTS-1:0] vco_clkout; | |
reg [CLKFB_DIV_BITS+CLKOUT_DIV_BITS-1:0] TOTAL_FBDIV; | |
wire clkfb_in = FEEDBACK_MODE ? clkfb : clkout[FEEDBACK_CLOCK]; | |
always @(CLKFB_DIV or CLKOUT_DIVS or FEEDBACK_CLOCK) begin | |
TOTAL_FBDIV = (CLKFB_DIV + 1) * (CLKOUT_DIV_VAL(FEEDBACK_CLOCK) + 1); | |
end | |
pll_clk_div #( | |
.DIV_BITS(CLKIN_DIV_BITS), | |
.DEL_BITS(1) | |
) clkin_div_inst ( | |
.clkin(clkin), | |
.rst(!resetn), | |
.ena(1'b1), | |
.clkout(pfd_clkin), | |
.CLKDIV_EN(1'b1), | |
.CLK_DIV(CLKIN_DIV), | |
.CLK_DEL(1'b0) | |
); | |
pll_clk_div #( | |
.DIV_BITS(CLKFB_DIV_BITS), | |
.DEL_BITS(1) | |
) clkfb_div_inst ( | |
.clkin(clkfb_in), | |
.rst(!resetn), | |
.ena(1'b1), | |
.clkout(pfd_clkfb), | |
.CLKDIV_EN(1'b1), | |
.CLK_DIV(CLKFB_DIV), | |
.CLK_DEL(1'b0) | |
); | |
generate | |
genvar i; | |
for (i = 0; i < NUM_CLKOUTS; i = i + 1) begin | |
pll_clk_div #( | |
.DIV_BITS(CLKOUT_DIV_BITS), | |
.DEL_BITS(CLKOUT_DEL_BITS) | |
) clkout_div_inst ( | |
.clkin(vco_clkout[i]), | |
.rst(!resetn), | |
.ena(clkouten[i]), | |
.clkout(clkout[i]), | |
.CLKDIV_EN(CLKDIV_EN[i]), | |
.CLK_DIV(CLKOUT_DIVS[CLKOUT_DIV_BITS*(i + 1) - 1 -:CLKOUT_DIV_BITS]), | |
.CLK_DEL(CLKOUT_DELS[CLKOUT_DEL_BITS*(i + 1) - 1 -:CLKOUT_DEL_BITS]) | |
); | |
end | |
endgenerate | |
alta_pll_core #( | |
.NUM_CLKOUTS (NUM_CLKOUTS ), | |
.TOTAL_FBDIV_BITS (CLKFB_DIV_BITS + CLKOUT_DIV_BITS), | |
.CLKOUT_PHASE_BITS(CLKOUT_PHASE_BITS) | |
) core_inst ( | |
.pllen (pllen ), | |
.pfden (1'b1 ), | |
.pfd_clkin (pfd_clkin ), | |
.pfd_clkfb (pfd_clkfb ), | |
.vco_clkout (vco_clkout ), | |
.vco_taps ( ), | |
.lock (lock_int ), | |
.TOTAL_FBDIV (TOTAL_FBDIV ), | |
.CLKOUT_PHASES(CLKOUT_PHASES) | |
); | |
parameter LOCK_COUNTER_BITS = 7; | |
reg [LOCK_COUNTER_BITS-1:0] lock_counter = {LOCK_COUNTER_BITS{1'b0}}; | |
always @(posedge pfd_clkfb or negedge resetn or negedge lock_int) begin | |
if (!resetn || !lock_int) begin | |
lock <= 1'b0; | |
lock_counter <= {LOCK_COUNTER_BITS{1'b0}}; | |
end else if (lock_counter == {LOCK_COUNTER_BITS{1'b1}}) begin | |
lock <= 1'b1; | |
end else if (!lock) begin | |
lock_counter <= lock_counter + 1; | |
end | |
end | |
function integer clogb2(input integer n); | |
begin | |
clogb2 = 0; | |
n = n - 1; | |
while (n != 0) begin | |
clogb2 = clogb2 + 1; | |
n = n >> 1; | |
end | |
end | |
endfunction | |
function [CLKOUT_DIV_BITS-1:0] CLKOUT_DIV_VAL(input integer clk_id); | |
begin | |
CLKOUT_DIV_VAL = CLKOUT_DIVS[CLKOUT_DIV_BITS * (clk_id + 1) - 1-:CLKOUT_DIV_BITS]; | |
end | |
endfunction | |
endmodule | |
module pll_clk_div_hl #(parameter DIV_BITS = 8, DEL_BITS = 8) ( | |
input clkin, rst, ena, | |
input CLKDIV_EN, | |
input [DIV_BITS-1:0] CLK_DIV_H, CLK_DIV_L, | |
input [DEL_BITS-1:0] CLK_DEL, | |
output clkout, bypass_clk | |
); | |
reg clk = 1'b0; | |
reg [DIV_BITS-1:0] divcnt_h = 0; | |
reg [DIV_BITS-1:0] divcnt_l = 0; | |
reg [DEL_BITS-1:0] dlycnt = 0; | |
reg rst_sync1 = 1'b0; | |
reg rst_sync2 = 1'b0; | |
reg divcnt_en = 1'b0, divcnt_en_dly = 1'b0; | |
reg clk_ena = 1'b0; | |
always @(*) begin | |
if (rst) begin | |
clk_ena <= 1'b0; | |
end else if (!clk) begin | |
clk_ena <= ena; | |
end | |
end | |
assign clkout = clk & clk_ena; | |
assign bypass_clk = clkin; | |
wire rstn = !rst && CLKDIV_EN; | |
always@(posedge clkin or negedge rstn) begin | |
if(!rstn) begin | |
rst_sync1 <= 0; | |
rst_sync2 <= 0; | |
end else begin | |
rst_sync1 <= 1; | |
rst_sync2 <= rst_sync1; | |
end | |
end | |
always@(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
dlycnt <= 0; | |
else if(!divcnt_en) | |
dlycnt <= dlycnt + 1; | |
end | |
always@(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
divcnt_en <= 0; | |
else if(dlycnt == CLK_DEL) | |
divcnt_en <= 1; | |
end | |
always@(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
divcnt_en_dly <= 0; | |
else | |
divcnt_en_dly <= divcnt_en; | |
end | |
always@(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
divcnt_h <= 0; | |
else if(divcnt_h == CLK_DIV_H) | |
divcnt_h <= 0; | |
else if(clk && divcnt_en_dly) | |
divcnt_h <= divcnt_h + 1; | |
end | |
always@(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
divcnt_l <= 0; | |
else if(divcnt_l == CLK_DIV_L) | |
divcnt_l <= 0; | |
else if(!clk && divcnt_en_dly) | |
divcnt_l <= divcnt_l + 1; | |
end | |
always@(posedge clkin or negedge rst_sync2) begin | |
if (!rst_sync2) | |
clk <= 0; | |
else if(divcnt_en && !divcnt_en_dly) | |
clk <= 1; | |
else if((divcnt_l == CLK_DIV_L) && !clk && divcnt_en_dly) | |
clk <= 1; | |
else if((divcnt_h == CLK_DIV_H) && clk && divcnt_en_dly) | |
clk <= 0; | |
end | |
endmodule | |
module alta_pll_sim_v #( | |
parameter NUM_CLKOUTS = 5, | |
CLKIN_DIV_BITS = 9, | |
CLKFB_DIV_BITS = 9, | |
CLKFB_DEL_BITS = 8, | |
CLKOUT_DIV_BITS = 8, | |
CLKOUT_DEL_BITS = 8, | |
CLKOUT_PHASE_BITS = 3) ( | |
input clkin, clkfb, | |
input pllen, resetn, | |
input [NUM_CLKOUTS-1:0] clkouten, | |
output [NUM_CLKOUTS-1:0] clkout, | |
output clkfbout, | |
output reg lock, | |
input [2:0] FEEDBACK_MODE, | |
input [CLKIN_DIV_BITS-1:0] CLKIN_DIV, | |
input [CLKFB_DIV_BITS-1:0] CLKFB_DIV, | |
input [CLKFB_DEL_BITS-1:0] CLKFB_DEL, | |
input CLKFB_TRIM, | |
input [CLKOUT_PHASE_BITS-1:0] CLKFB_PHASE, | |
input [NUM_CLKOUTS-1:0] CLKDIV_EN, | |
input [CLKOUT_DIV_BITS*NUM_CLKOUTS-1:0] CLKOUT_DIVS_H, | |
input [CLKOUT_DIV_BITS*NUM_CLKOUTS-1:0] CLKOUT_DIVS_L, | |
input [CLKOUT_DEL_BITS*NUM_CLKOUTS-1:0] CLKOUT_DELS, | |
input [NUM_CLKOUTS-1:0] CLKOUT_TRIM, | |
input [NUM_CLKOUTS-1:0] CLKOUT_BYPASS, | |
input [NUM_CLKOUTS-1:0] CLKOUT_CASCADE, | |
input [CLKOUT_PHASE_BITS*NUM_CLKOUTS-1:0] CLKOUT_PHASES | |
); | |
wire [NUM_CLKOUTS:0] vco_clkout; | |
wire [CLKFB_DIV_BITS:0] TOTAL_FBDIV = CLKFB_DIV + 1; | |
wire pfd_clkfb = (FEEDBACK_MODE == 3'b001 || FEEDBACK_MODE == 3'b111) ? 1'bx : (FEEDBACK_MODE == 3'b010) ? clkfbout : clkfb; | |
wire [7:0] CLKIN_DIV_H = (CLKIN_DIV == 0) ? 8'h00 :CLKIN_DIV[8:1]; | |
wire [7:0] CLKIN_DIV_L = (CLKIN_DIV == 0) ? 8'h00 :CLKIN_DIV[8:1] - !CLKIN_DIV[0]; | |
pll_clk_div_hl #( | |
.DIV_BITS(CLKIN_DIV_BITS-1), | |
.DEL_BITS(1) | |
) clkin_div_inst ( | |
.clkin(clkin), | |
.rst(!resetn), | |
.ena(1'b1), | |
.clkout(div_clkin), | |
.bypass_clk(bypass_clkin), | |
.CLKDIV_EN(1'b1), | |
.CLK_DIV_H(CLKIN_DIV_H), | |
.CLK_DIV_L(CLKIN_DIV_L), | |
.CLK_DEL(1'b0) | |
); | |
wire pfd_clkin = (|CLKIN_DIV == 0) ? bypass_clkin : div_clkin; | |
wire [7:0] CLKFB_DIV_H = (CLKFB_DIV == 0) ? 8'h00 :CLKFB_DIV[8:1]; | |
wire [7:0] CLKFB_DIV_L = (CLKFB_DIV == 0) ? 8'h00 :CLKFB_DIV[8:1] - !CLKFB_DIV[0]; | |
pll_clk_div_hl #( | |
.DIV_BITS(CLKFB_DIV_BITS-1), | |
.DEL_BITS(CLKFB_DEL_BITS) | |
) clkfb_div_inst ( | |
.clkin(vco_clkout[NUM_CLKOUTS]), | |
.rst(!resetn), | |
.ena(1'b1), | |
.clkout(clkfbout_div), | |
.bypass_clk(bypass_clkfb), | |
.CLKDIV_EN(1'b1), | |
.CLK_DIV_H(CLKFB_DIV_H), | |
.CLK_DIV_L(CLKFB_DIV_L), | |
.CLK_DEL(CLKFB_DEL) | |
); | |
pll_clk_trim clkfb_trim_inst( | |
.clkin(bypass_clkfb), | |
.divclk(clkfbout_div), | |
.TRIM(CLKFB_TRIM), | |
.BYPASS(1'b0), | |
.CFG_EN(1'b1), | |
.clkout(clkfbout) | |
); | |
wire [NUM_CLKOUTS-1:0] div_clk, bypass_clk, mux_clk; | |
generate | |
genvar i; | |
for (i = 0; i < NUM_CLKOUTS; i = i + 1) begin | |
if (i == 0) begin | |
assign mux_clk[i] = vco_clkout[i]; | |
end else begin | |
assign mux_clk[i] = CLKOUT_CASCADE[i] ? clkout[i-1] : vco_clkout[i]; | |
end | |
pll_clk_div_hl #( | |
.DIV_BITS(CLKOUT_DIV_BITS), | |
.DEL_BITS(CLKOUT_DEL_BITS) | |
) clkout_div_inst ( | |
.clkin(mux_clk[i]), | |
.rst(!resetn), | |
.ena(clkouten[i]), | |
.clkout(div_clk[i]), | |
.bypass_clk(bypass_clk[i]), | |
.CLKDIV_EN(CLKDIV_EN[i]), | |
.CLK_DIV_H(CLKOUT_DIVS_H[CLKOUT_DIV_BITS*(i + 1) - 1 -:CLKOUT_DIV_BITS]), | |
.CLK_DIV_L(CLKOUT_DIVS_L[CLKOUT_DIV_BITS*(i + 1) - 1 -:CLKOUT_DIV_BITS]), | |
.CLK_DEL(CLKOUT_DELS[CLKOUT_DEL_BITS*(i + 1) - 1 -:CLKOUT_DEL_BITS]) | |
); | |
pll_clk_trim clkout_trim_inst( | |
.clkin(bypass_clk[i]), | |
.divclk(div_clk[i]), | |
.TRIM(CLKOUT_TRIM[i]), | |
.BYPASS(CLKOUT_BYPASS[i]), | |
.CFG_EN(1'b1), | |
.clkout(clkout[i]) | |
); | |
end | |
endgenerate | |
alta_pll_core #( | |
.NUM_CLKOUTS (NUM_CLKOUTS+1 ), | |
.TOTAL_FBDIV_BITS (CLKFB_DIV_BITS+1 ), | |
.CLKOUT_PHASE_BITS(CLKOUT_PHASE_BITS) | |
) core_inst ( | |
.pllen (pllen ), | |
.pfden (1'b1 ), | |
.pfd_clkin (pfd_clkin ), | |
.pfd_clkfb (pfd_clkfb ), | |
.vco_clkout (vco_clkout ), | |
.vco_taps ( ), | |
.lock (lock_int ), | |
.TOTAL_FBDIV (TOTAL_FBDIV ), | |
.CLKOUT_PHASES({CLKFB_PHASE, CLKOUT_PHASES}) | |
); | |
parameter LOCK_COUNTER_BITS = 7; | |
reg [LOCK_COUNTER_BITS-1:0] lock_counter = {LOCK_COUNTER_BITS{1'b0}}; | |
always @(posedge pfd_clkfb or negedge resetn or negedge lock_int) begin | |
if (!resetn || !lock_int) begin | |
lock <= 1'b0; | |
lock_counter <= {LOCK_COUNTER_BITS{1'b0}}; | |
end else if (lock_counter == {LOCK_COUNTER_BITS{1'b1}}) begin | |
lock <= 1'b1; | |
end else if (!lock) begin | |
lock_counter <= lock_counter + 1; | |
end | |
end | |
endmodule | |
module pll_clk_div_hl_ve #(parameter DIV_BITS = 8, DEL_BITS = 8) ( | |
input clkin, rst, | |
input CLKDIV_EN, | |
input [DIV_BITS-1:0] CLK_DIV_H, CLK_DIV_L, | |
input [DEL_BITS-1:0] CLK_DEL, | |
output clkout, bypass_clk | |
); | |
reg clk = 1'b0; | |
reg [DIV_BITS-1:0] divcnt_h = 0; | |
reg [DIV_BITS-1:0] divcnt_l = 0; | |
reg [DEL_BITS-1:0] dlycnt = 0; | |
reg divcnt_en = 1'b0, divcnt_en_dly = 1'b0; | |
assign clkout = clk; | |
assign bypass_clk = clkin; | |
wire rstn = !rst & CLKDIV_EN; | |
always@(posedge clkin or negedge rstn) begin | |
if (!rstn) | |
dlycnt <= 0; | |
else if(!divcnt_en) | |
dlycnt <= dlycnt + 1; | |
end | |
always@(posedge clkin or negedge rstn) begin | |
if (!rstn) | |
divcnt_en <= 0; | |
else if(dlycnt == CLK_DEL) | |
divcnt_en <= 1; | |
end | |
always@(posedge clkin or negedge rstn) begin | |
if (!rstn) | |
divcnt_en_dly <= 0; | |
else | |
divcnt_en_dly <= divcnt_en; | |
end | |
always@(posedge clkin or negedge rstn) begin | |
if (!rstn) | |
divcnt_h <= 0; | |
else if(divcnt_h == CLK_DIV_H) | |
divcnt_h <= 0; | |
else if(clk && divcnt_en_dly) | |
divcnt_h <= divcnt_h + 1; | |
end | |
always@(posedge clkin or negedge rstn) begin | |
if (!rstn) | |
divcnt_l <= 0; | |
else if(divcnt_l == CLK_DIV_L) | |
divcnt_l <= 0; | |
else if(!clk && divcnt_en_dly) | |
divcnt_l <= divcnt_l + 1; | |
end | |
always@(posedge clkin or negedge rstn) begin | |
if (!rstn) | |
clk <= 0; | |
else if(divcnt_en && !divcnt_en_dly) | |
clk <= 1; | |
else if((divcnt_l == CLK_DIV_L) && !clk && divcnt_en_dly) | |
clk <= 1; | |
else if((divcnt_h == CLK_DIV_H) && clk && divcnt_en_dly) | |
clk <= 0; | |
end | |
endmodule | |
module alta_pll_sim_ve #( | |
parameter NUM_CLKOUTS = 5, | |
CLKFB_DEL_BITS = 8, | |
CLKOUT_DIV_BITS = 8, | |
CLKOUT_DEL_BITS = 8, | |
CLKOUT_PHASE_BITS = 3) ( | |
input clkin, clkfb, | |
input pfden, resetn, | |
input [2:0] phasecounterselect, | |
input phaseupdown, phasestep, scanclk, | |
output phasedone, | |
output [NUM_CLKOUTS-1:0] clkout, | |
output clkfbout, | |
output reg lock, | |
input [2:0] FEEDBACK_MODE, | |
input VCO_POST_DIV, | |
input [CLKOUT_DIV_BITS-1:0] CLKIN_DIV_H, CLKIN_DIV_L, | |
input [CLKOUT_DIV_BITS-1:0] CLKFB_DIV_H, CLKFB_DIV_L, | |
input CLKIN_BYPASS, CLKFB_BYPASS, | |
input [CLKFB_DEL_BITS-1:0] CLKFB_DEL, | |
input CLKFB_TRIM, | |
input [CLKOUT_PHASE_BITS-1:0] CLKFB_PHASE, | |
input [NUM_CLKOUTS-1:0] CLKDIV_EN, | |
input [CLKOUT_DIV_BITS*NUM_CLKOUTS-1:0] CLKOUT_DIVS_H, | |
input [CLKOUT_DIV_BITS*NUM_CLKOUTS-1:0] CLKOUT_DIVS_L, | |
input [CLKOUT_DEL_BITS*NUM_CLKOUTS-1:0] CLKOUT_DELS, | |
input [NUM_CLKOUTS-1:0] CLKOUT_TRIM, | |
input [NUM_CLKOUTS-1:0] CLKOUT_BYPASS, | |
input [NUM_CLKOUTS-1:0] CLKOUT_CASCADE, | |
input [CLKOUT_PHASE_BITS*NUM_CLKOUTS-1:0] CLKOUT_PHASES | |
); | |
wire [NUM_CLKOUTS:0] vco_clkout; | |
wire [CLKOUT_DIV_BITS:0] TOTAL_FBDIV = CLKFB_BYPASS ? 1 : (CLKFB_DIV_H + CLKFB_DIV_L + 2); | |
wire pfd_clkfb = (FEEDBACK_MODE == 3'b001 || FEEDBACK_MODE == 3'b111) ? 1'bx : (FEEDBACK_MODE == 3'b010) ? clkfbout : clkfb; | |
pll_clk_div_hl_ve #( | |
.DIV_BITS(CLKOUT_DIV_BITS), | |
.DEL_BITS(1) | |
) clkin_div_inst ( | |
.clkin(clkin), | |
.rst(!resetn), | |
.clkout(div_clkin), | |
.bypass_clk(bypass_clkin), | |
.CLKDIV_EN(1'b1), | |
.CLK_DIV_H(CLKIN_DIV_H), | |
.CLK_DIV_L(CLKIN_DIV_L), | |
.CLK_DEL(1'b0) | |
); | |
wire pfd_clkin = CLKIN_BYPASS ? bypass_clkin : div_clkin; | |
pll_clk_div_hl_ve #( | |
.DIV_BITS(CLKOUT_DIV_BITS), | |
.DEL_BITS(CLKFB_DEL_BITS) | |
) clkfb_div_inst ( | |
.clkin(vco_clkout[NUM_CLKOUTS]), | |
.rst(!resetn), | |
.clkout(clkfbout_div), | |
.bypass_clk(bypass_clkfb), | |
.CLKDIV_EN(1'b1), | |
.CLK_DIV_H(CLKFB_DIV_H), | |
.CLK_DIV_L(CLKFB_DIV_L), | |
.CLK_DEL(CLKFB_DEL) | |
); | |
pll_clk_trim clkfb_trim_inst( | |
.clkin(bypass_clkfb), | |
.divclk(clkfbout_div), | |
.TRIM(CLKFB_TRIM), | |
.BYPASS(1'b0), | |
.CFG_EN(1'b1), | |
.clkout(clkfbout) | |
); | |
wire [NUM_CLKOUTS-1:0] div_clk, bypass_clk, mux_clk; | |
generate | |
genvar i; | |
for (i = 0; i < NUM_CLKOUTS; i = i + 1) begin | |
if (i == 0) begin | |
assign mux_clk[i] = vco_clkout[i]; | |
end else begin | |
assign mux_clk[i] = CLKOUT_CASCADE[i] ? clkout[i-1] : vco_clkout[i]; | |
end | |
pll_clk_div_hl_ve #( | |
.DIV_BITS(CLKOUT_DIV_BITS), | |
.DEL_BITS(CLKOUT_DEL_BITS) | |
) clkout_div_inst ( | |
.clkin(mux_clk[i]), | |
.rst(!resetn), | |
.clkout(div_clk[i]), | |
.bypass_clk(bypass_clk[i]), | |
.CLKDIV_EN(CLKDIV_EN[i]), | |
.CLK_DIV_H(CLKOUT_DIVS_H[CLKOUT_DIV_BITS*(i + 1) - 1 -:CLKOUT_DIV_BITS]), | |
.CLK_DIV_L(CLKOUT_DIVS_L[CLKOUT_DIV_BITS*(i + 1) - 1 -:CLKOUT_DIV_BITS]), | |
.CLK_DEL(CLKOUT_DELS[CLKOUT_DEL_BITS*(i + 1) - 1 -:CLKOUT_DEL_BITS]) | |
); | |
pll_clk_trim clkout_trim_inst( | |
.clkin(bypass_clk[i]), | |
.divclk(div_clk[i]), | |
.TRIM(CLKOUT_TRIM[i]), | |
.BYPASS(CLKOUT_BYPASS[i]), | |
.CFG_EN(CLKDIV_EN[i]), | |
.clkout(clkout[i]) | |
); | |
end | |
endgenerate | |
reg [NUM_CLKOUTS:0] phase_counter_en = {(NUM_CLKOUTS+1){1'b0}}; | |
reg phase_shift_dir = 1'b0, phase_update = 1'b0; | |
reg phase_shift_en0 = 1'b0, phase_shift_en1 = 1'b0, phase_shift_en2 = 1'b0; | |
always @ (negedge scanclk or negedge resetn) begin | |
if (!resetn) begin | |
phase_shift_en0 <= 1'b0; | |
phase_shift_en1 <= 1'b0; | |
phase_shift_en2 <= 1'b0; | |
end else begin | |
phase_shift_en0 <= phasestep; | |
phase_shift_en1 <= phase_shift_en0; | |
phase_shift_en2 <= phase_shift_en1; | |
end | |
end | |
always @ (posedge scanclk or negedge resetn) begin | |
if (!resetn) begin | |
phase_shift_dir <= 1'b0; | |
phase_update <= 1'b0; | |
phase_counter_en <= {(NUM_CLKOUTS+1){1'b0}}; | |
end else if (phase_shift_en1 & !phase_shift_en2) begin | |
phase_shift_dir <= phaseupdown; | |
if (phasecounterselect != 3'b111) begin | |
phase_update <= 1'b1; | |
case (phasecounterselect) | |
3'b000: phase_counter_en <= {1'b0, {NUM_CLKOUTS{1'b1}}}; // All output counters | |
3'b001: phase_counter_en <= {1'b1, {NUM_CLKOUTS{1'b0}}}; // Feedback counter | |
default: phase_counter_en <= (1 << phasecounterselect - 2); // Specific counter | |
endcase | |
end | |
end else if (phase_shift_en2) begin | |
phase_counter_en <= {(NUM_CLKOUTS+1){1'b0}}; | |
end | |
end | |
wire [CLKOUT_PHASE_BITS*(NUM_CLKOUTS+1)-1:0] CLKOUT_PHASES_ALL = {CLKFB_PHASE, CLKOUT_PHASES}; | |
wire [CLKOUT_PHASE_BITS*(NUM_CLKOUTS+1)-1:0] CLKOUT_PHASES_CNT; | |
reg [CLKOUT_PHASE_BITS*(NUM_CLKOUTS+1)-1:0] CLKOUT_PHASES_REG; | |
reg [CLKOUT_PHASE_BITS*(NUM_CLKOUTS+1)-1:0] CLKOUT_PHASES_INT; | |
generate | |
genvar j; | |
for (j = 0; j <= NUM_CLKOUTS; j = j + 1) begin : PHASE_SHIFT | |
assign CLKOUT_PHASES_CNT[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j] = CLKOUT_PHASES_REG[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j] + (phase_shift_dir ? 1 : -1); | |
always @ (posedge scanclk or negedge resetn) begin | |
if (!resetn) begin | |
#0.001 CLKOUT_PHASES_REG[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j] <= CLKOUT_PHASES_ALL[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j]; | |
end else if (phase_counter_en[j]) begin | |
CLKOUT_PHASES_REG[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j] <= CLKOUT_PHASES_CNT[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j]; | |
end | |
end | |
always @ (negedge vco_clkout[j] or negedge resetn) begin | |
if (!resetn) begin | |
#0.001 CLKOUT_PHASES_INT[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j] <= CLKOUT_PHASES_ALL[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j]; | |
end else if (phase_counter_en[j] & !scanclk) begin | |
CLKOUT_PHASES_INT[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j] <= CLKOUT_PHASES_CNT[CLKOUT_PHASE_BITS*(j+1)-1:CLKOUT_PHASE_BITS*j]; | |
phase_update <= 1'b0; | |
end | |
end | |
end | |
endgenerate | |
assign phasedone = !phase_update; | |
alta_pll_core #( | |
.NUM_CLKOUTS (NUM_CLKOUTS+1 ), | |
.TOTAL_FBDIV_BITS (CLKOUT_DIV_BITS+1), | |
.CLKOUT_PHASE_BITS(CLKOUT_PHASE_BITS) | |
) core_inst ( | |
.pllen (resetn ), | |
.pfden (pfden ), | |
.pfd_clkin (pfd_clkin ), | |
.pfd_clkfb (pfd_clkfb ), | |
.vco_clkout (vco_clkout ), | |
.vco_taps ( ), | |
.lock (lock_int ), | |
.TOTAL_FBDIV (VCO_POST_DIV ? (TOTAL_FBDIV << 1) : TOTAL_FBDIV), | |
.CLKOUT_PHASES(CLKOUT_PHASES_INT) | |
); | |
parameter LOCK_COUNTER_BITS = 7; | |
reg [LOCK_COUNTER_BITS-1:0] lock_counter = {LOCK_COUNTER_BITS{1'b0}}; | |
always @(posedge pfd_clkfb or negedge resetn or negedge lock_int) begin | |
if (!resetn || !lock_int) begin | |
lock <= 1'b0; | |
lock_counter <= {LOCK_COUNTER_BITS{1'b0}}; | |
end else if (lock_counter == {LOCK_COUNTER_BITS{1'b1}}) begin | |
lock <= 1'b1; | |
end else if (!lock) begin | |
lock_counter <= lock_counter + 1; | |
end | |
end | |
endmodule | |
`endif | |
module pll_clk_trim ( | |
input clkin, divclk, | |
input TRIM, BYPASS, CFG_EN, | |
output clkout | |
); | |
reg trim_clk = 1'b1; | |
always @ (clkin or divclk) begin | |
if (!clkin ^ divclk) begin | |
trim_clk = clkin; | |
end | |
end | |
assign clkout = BYPASS ? (clkin & CFG_EN) : TRIM ? trim_clk : divclk; | |
endmodule | |
module alta_pllv ( | |
input clkin, clkfb, | |
input pllen, resetn, | |
input clkout0en, clkout1en, clkout2en, clkout3en, clkout4en, | |
output clkout0, clkout1, clkout2, clkout3, clkout4, | |
output clkfbout, lock | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter CLKIN_DIV = 9'b0; | |
parameter CLKFB_DIV = 9'b0; | |
parameter CLKDIV0_EN = 1'b0; | |
parameter CLKDIV1_EN = 1'b0; | |
parameter CLKDIV2_EN = 1'b0; | |
parameter CLKDIV3_EN = 1'b0; | |
parameter CLKDIV4_EN = 1'b0; | |
parameter CLKOUT0_HIGH = 8'b0; | |
parameter CLKOUT0_LOW = 8'b0; | |
parameter CLKOUT0_TRIM = 1'b0; | |
parameter CLKOUT0_BYPASS = 1'b0; | |
parameter CLKOUT1_HIGH = 8'b0; | |
parameter CLKOUT1_LOW = 8'b0; | |
parameter CLKOUT1_TRIM = 1'b0; | |
parameter CLKOUT1_BYPASS = 1'b0; | |
parameter CLKOUT2_HIGH = 8'b0; | |
parameter CLKOUT2_LOW = 8'b0; | |
parameter CLKOUT2_TRIM = 1'b0; | |
parameter CLKOUT2_BYPASS = 1'b0; | |
parameter CLKOUT3_HIGH = 8'b0; | |
parameter CLKOUT3_LOW = 8'b0; | |
parameter CLKOUT3_TRIM = 1'b0; | |
parameter CLKOUT3_BYPASS = 1'b0; | |
parameter CLKOUT4_HIGH = 8'b0; | |
parameter CLKOUT4_LOW = 8'b0; | |
parameter CLKOUT4_TRIM = 1'b0; | |
parameter CLKOUT4_BYPASS = 1'b0; | |
parameter CLKOUT0_DEL = 8'b0; | |
parameter CLKOUT1_DEL = 8'b0; | |
parameter CLKOUT2_DEL = 8'b0; | |
parameter CLKOUT3_DEL = 8'b0; | |
parameter CLKOUT4_DEL = 8'b0; | |
parameter CLKOUT0_PHASE = 3'b0; | |
parameter CLKOUT1_PHASE = 3'b0; | |
parameter CLKOUT2_PHASE = 3'b0; | |
parameter CLKOUT3_PHASE = 3'b0; | |
parameter CLKOUT4_PHASE = 3'b0; | |
parameter CLKFB_DEL = 8'b0; | |
parameter CLKFB_PHASE = 3'b0; | |
parameter CLKFB_TRIM = 1'b0; | |
parameter FEEDBACK_MODE = 3'b0; | |
parameter FBDELAY_VAL = 3'b0; | |
parameter PLLOUTP_EN = 1'b0; | |
parameter PLLOUTN_EN = 1'b0; | |
parameter CLKOUT1_CASCADE = 1'b0; | |
parameter CLKOUT2_CASCADE = 1'b0; | |
parameter CLKOUT3_CASCADE = 1'b0; | |
parameter CLKOUT4_CASCADE = 1'b0; | |
parameter CP = 3'b111; | |
parameter RREF = 2'b00; | |
parameter RVI = 2'b00; | |
`ifdef ALTA_SIM | |
alta_pll_sim_v #( | |
.NUM_CLKOUTS (5), | |
.CLKIN_DIV_BITS (9), | |
.CLKFB_DIV_BITS (9), | |
.CLKOUT_DIV_BITS (8), | |
.CLKOUT_DEL_BITS (8), | |
.CLKOUT_PHASE_BITS(3) | |
) sim_inst ( | |
.clkin (clkin ), | |
.clkfb (clkfb ), | |
.clkfbout (clkfbout ), | |
.pllen (pllen ), | |
.resetn (resetn ), | |
.clkout ({clkout4 , clkout3 , clkout2 , clkout1 , clkout0 }), | |
.clkouten ({clkout4en, clkout3en, clkout2en, clkout1en, clkout0en}), | |
.lock (lock ), | |
.FEEDBACK_MODE(FEEDBACK_MODE), | |
.CLKIN_DIV (CLKIN_DIV ), | |
.CLKFB_DIV (CLKFB_DIV ), | |
.CLKFB_DEL (CLKFB_DEL ), | |
.CLKFB_TRIM (CLKFB_TRIM ), | |
.CLKFB_PHASE(CLKFB_PHASE), | |
.CLKDIV_EN ({CLKDIV4_EN , CLKDIV3_EN , CLKDIV2_EN , CLKDIV1_EN , CLKDIV0_EN }), | |
.CLKOUT_DIVS_H ({CLKOUT4_HIGH , CLKOUT3_HIGH , CLKOUT2_HIGH , CLKOUT1_HIGH , CLKOUT0_HIGH }), | |
.CLKOUT_DIVS_L ({CLKOUT4_LOW , CLKOUT3_LOW , CLKOUT2_LOW , CLKOUT1_LOW , CLKOUT0_LOW }), | |
.CLKOUT_DELS ({CLKOUT4_DEL , CLKOUT3_DEL , CLKOUT2_DEL , CLKOUT1_DEL , CLKOUT0_DEL }), | |
.CLKOUT_TRIM ({CLKOUT4_TRIM , CLKOUT3_TRIM , CLKOUT2_TRIM , CLKOUT1_TRIM , CLKOUT0_TRIM }), | |
.CLKOUT_BYPASS ({CLKOUT4_BYPASS , CLKOUT3_BYPASS , CLKOUT2_BYPASS , CLKOUT1_BYPASS , CLKOUT0_BYPASS}), | |
.CLKOUT_CASCADE({CLKOUT4_CASCADE, CLKOUT3_CASCADE, CLKOUT2_CASCADE, CLKOUT1_CASCADE, 1'b0 }), | |
.CLKOUT_PHASES ({CLKOUT4_PHASE , CLKOUT3_PHASE , CLKOUT2_PHASE , CLKOUT1_PHASE , CLKOUT0_PHASE }) | |
); | |
`else | |
assign clkout0 = clkout0en & clkin; | |
assign clkout1 = clkout1en & clkin; | |
assign clkout2 = clkout2en & clkin; | |
assign clkout3 = clkout3en & clkin; | |
assign clkout4 = clkout4en & clkin; | |
assign lock = pllen & resetn & clkfb; | |
`endif | |
endmodule | |
module alta_pllve ( | |
input clkin, clkfb, | |
input pfden, resetn, | |
input [2:0] phasecounterselect, | |
input phaseupdown, phasestep, | |
input scanclk, scanclkena, scandata, configupdate, | |
output scandataout, scandone, phasedone, | |
output clkout0, clkout1, clkout2, clkout3, clkout4, | |
output clkfbout, lock | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter CLKIN_HIGH = 8'b0; | |
parameter CLKIN_LOW = 8'b0; | |
parameter CLKIN_BYPASS = 1'b0; | |
parameter CLKIN_TRIM = 1'b0; | |
parameter CLKFB_HIGH = 8'b0; | |
parameter CLKFB_LOW = 8'b0; | |
parameter CLKFB_BYPASS = 1'b0; | |
parameter CLKFB_TRIM = 1'b0; | |
parameter CLKDIV0_EN = 1'b0; | |
parameter CLKDIV1_EN = 1'b0; | |
parameter CLKDIV2_EN = 1'b0; | |
parameter CLKDIV3_EN = 1'b0; | |
parameter CLKDIV4_EN = 1'b0; | |
parameter CLKOUT0_HIGH = 8'b0; | |
parameter CLKOUT0_LOW = 8'b0; | |
parameter CLKOUT0_TRIM = 1'b0; | |
parameter CLKOUT0_BYPASS = 1'b0; | |
parameter CLKOUT1_HIGH = 8'b0; | |
parameter CLKOUT1_LOW = 8'b0; | |
parameter CLKOUT1_TRIM = 1'b0; | |
parameter CLKOUT1_BYPASS = 1'b0; | |
parameter CLKOUT2_HIGH = 8'b0; | |
parameter CLKOUT2_LOW = 8'b0; | |
parameter CLKOUT2_TRIM = 1'b0; | |
parameter CLKOUT2_BYPASS = 1'b0; | |
parameter CLKOUT3_HIGH = 8'b0; | |
parameter CLKOUT3_LOW = 8'b0; | |
parameter CLKOUT3_TRIM = 1'b0; | |
parameter CLKOUT3_BYPASS = 1'b0; | |
parameter CLKOUT4_HIGH = 8'b0; | |
parameter CLKOUT4_LOW = 8'b0; | |
parameter CLKOUT4_TRIM = 1'b0; | |
parameter CLKOUT4_BYPASS = 1'b0; | |
parameter CLKOUT0_DEL = 8'b0; | |
parameter CLKOUT1_DEL = 8'b0; | |
parameter CLKOUT2_DEL = 8'b0; | |
parameter CLKOUT3_DEL = 8'b0; | |
parameter CLKOUT4_DEL = 8'b0; | |
parameter CLKOUT0_PHASE = 3'b0; | |
parameter CLKOUT1_PHASE = 3'b0; | |
parameter CLKOUT2_PHASE = 3'b0; | |
parameter CLKOUT3_PHASE = 3'b0; | |
parameter CLKOUT4_PHASE = 3'b0; | |
parameter CLKFB_DEL = 8'b0; | |
parameter CLKFB_PHASE = 3'b0; | |
parameter FEEDBACK_MODE = 3'b0; | |
parameter FBDELAY_VAL = 3'b0; | |
parameter PLLOUTP_EN = 1'b0; | |
parameter PLLOUTN_EN = 1'b0; | |
parameter CLKOUT1_CASCADE = 1'b0; | |
parameter CLKOUT2_CASCADE = 1'b0; | |
parameter CLKOUT3_CASCADE = 1'b0; | |
parameter CLKOUT4_CASCADE = 1'b0; | |
parameter VCO_POST_DIV = 1'b0; | |
parameter REG_CTRL = 2'b0; | |
parameter IVCO = 3'b100; | |
parameter CP = 3'b010; | |
parameter RREF = 2'b01; | |
parameter RLPF = 2'b01; | |
parameter RVI = 2'b01; | |
parameter [143:0] init_params = { IVCO, RVI, RREF, RLPF, | |
VCO_POST_DIV, 5'b0 /* DUMMY */, CP, | |
CLKIN_BYPASS, CLKIN_HIGH, CLKIN_TRIM, CLKIN_LOW, | |
CLKFB_BYPASS, CLKFB_HIGH, CLKFB_TRIM, CLKFB_LOW, | |
CLKOUT0_BYPASS, CLKOUT0_HIGH, CLKOUT0_TRIM, CLKOUT0_LOW, | |
CLKOUT1_BYPASS, CLKOUT1_HIGH, CLKOUT1_TRIM, CLKOUT1_LOW, | |
CLKOUT2_BYPASS, CLKOUT2_HIGH, CLKOUT2_TRIM, CLKOUT2_LOW, | |
CLKOUT3_BYPASS, CLKOUT3_HIGH, CLKOUT3_TRIM, CLKOUT3_LOW, | |
CLKOUT4_BYPASS, CLKOUT4_HIGH, CLKOUT4_TRIM, CLKOUT4_LOW}; | |
reg [143:0] shift_reg = init_params; | |
reg [143:0] param_reg = init_params; | |
// Reconfigurable parameters | |
wire RE_VCO_POST_DIV = param_reg[134:134]; | |
wire RE_CLKIN_BYPASS = param_reg[125:125]; | |
wire [7:0] RE_CLKIN_HIGH = param_reg[124:117]; | |
wire RE_CLKIN_TRIM = param_reg[116:116]; | |
wire [7:0] RE_CLKIN_LOW = param_reg[115:108]; | |
wire RE_CLKFB_BYPASS = param_reg[107:107]; | |
wire [7:0] RE_CLKFB_HIGH = param_reg[106:99]; | |
wire RE_CLKFB_TRIM = param_reg[98:98]; | |
wire [7:0] RE_CLKFB_LOW = param_reg[97:90]; | |
wire RE_CLKOUT0_BYPASS = param_reg[89:89]; | |
wire [7:0] RE_CLKOUT0_HIGH = param_reg[88:81]; | |
wire RE_CLKOUT0_TRIM = param_reg[80:80]; | |
wire [7:0] RE_CLKOUT0_LOW = param_reg[79:72]; | |
wire RE_CLKOUT1_BYPASS = param_reg[71:71]; | |
wire [7:0] RE_CLKOUT1_HIGH = param_reg[70:63]; | |
wire RE_CLKOUT1_TRIM = param_reg[62:62]; | |
wire [7:0] RE_CLKOUT1_LOW = param_reg[61:54]; | |
wire RE_CLKOUT2_BYPASS = param_reg[53:53]; | |
wire [7:0] RE_CLKOUT2_HIGH = param_reg[52:45]; | |
wire RE_CLKOUT2_TRIM = param_reg[44:44]; | |
wire [7:0] RE_CLKOUT2_LOW = param_reg[43:36]; | |
wire RE_CLKOUT3_BYPASS = param_reg[35:35]; | |
wire [7:0] RE_CLKOUT3_HIGH = param_reg[34:27]; | |
wire RE_CLKOUT3_TRIM = param_reg[26:26]; | |
wire [7:0] RE_CLKOUT3_LOW = param_reg[25:18]; | |
wire RE_CLKOUT4_BYPASS = param_reg[17:17]; | |
wire [7:0] RE_CLKOUT4_HIGH = param_reg[16:9]; | |
wire RE_CLKOUT4_TRIM = param_reg[8:8]; | |
wire [7:0] RE_CLKOUT4_LOW = param_reg[7:0]; | |
reg scanclkena_reg = 1'b0, datain_reg = 1'b0, dataout_reg = 1'b0; | |
always @ (negedge scanclk) begin | |
scanclkena_reg <= scanclkena; | |
end | |
wire scanclk_int = scanclk & scanclkena_reg; | |
always @ (*) begin | |
if (scanclk_int) | |
datain_reg <= scandata; | |
end | |
reg update_reg0, update_reg1, scandone_reg; | |
always @ (posedge scanclk) begin | |
update_reg0 <= configupdate; | |
update_reg1 <= update_reg0; | |
end | |
wire scandone_clk = update_reg0 & !update_reg1; | |
always @ (negedge scandone_clk or negedge resetn) begin | |
if (!resetn) begin | |
scandone_reg <= 1'b0; | |
end else begin | |
scandone_reg <= 1'b1; | |
end | |
end | |
assign scandone = scandone_reg; | |
always @ (posedge scanclk) begin | |
if (scanclkena) begin | |
shift_reg <= {datain_reg, shift_reg[143:1]}; | |
end | |
if (configupdate) begin | |
param_reg <= shift_reg; | |
end | |
end | |
wire dataout = shift_reg[0]; | |
always @ (negedge scanclk_int) begin | |
dataout_reg <= dataout; | |
end | |
assign scandataout = dataout_reg; | |
`ifdef ALTA_SIM | |
alta_pll_sim_ve #( | |
.NUM_CLKOUTS (5), | |
.CLKOUT_DIV_BITS (8), | |
.CLKOUT_DEL_BITS (8), | |
.CLKOUT_PHASE_BITS(3) | |
) sim_inst ( | |
.clkin (clkin ), | |
.clkfb (clkfb ), | |
.clkfbout (clkfbout ), | |
.pfden (pfden ), | |
.resetn (resetn ), | |
.phasecounterselect(phasecounterselect ), | |
.phaseupdown (phaseupdown ), | |
.phasestep (phasestep ), | |
.scanclk (scanclk ), | |
.phasedone (phasedone ), | |
.clkout ({clkout4, clkout3, clkout2, clkout1, clkout0}), | |
.lock (lock ), | |
.FEEDBACK_MODE(FEEDBACK_MODE), | |
.VCO_POST_DIV(RE_VCO_POST_DIV), | |
.CLKIN_DIV_H (RE_CLKIN_HIGH ), | |
.CLKIN_DIV_L (RE_CLKIN_LOW ), | |
.CLKIN_BYPASS(RE_CLKIN_BYPASS), | |
.CLKFB_DIV_H (RE_CLKFB_HIGH ), | |
.CLKFB_DIV_L (RE_CLKFB_LOW ), | |
.CLKFB_BYPASS(RE_CLKFB_BYPASS), | |
.CLKFB_TRIM (RE_CLKFB_TRIM ), | |
.CLKFB_DEL (CLKFB_DEL ), | |
.CLKFB_PHASE (CLKFB_PHASE ), | |
.CLKDIV_EN ({CLKDIV4_EN , CLKDIV3_EN , CLKDIV2_EN , CLKDIV1_EN , CLKDIV0_EN }), | |
.CLKOUT_DIVS_H ({RE_CLKOUT4_HIGH , RE_CLKOUT3_HIGH , RE_CLKOUT2_HIGH , RE_CLKOUT1_HIGH , RE_CLKOUT0_HIGH }), | |
.CLKOUT_DIVS_L ({RE_CLKOUT4_LOW , RE_CLKOUT3_LOW , RE_CLKOUT2_LOW , RE_CLKOUT1_LOW , RE_CLKOUT0_LOW }), | |
.CLKOUT_TRIM ({RE_CLKOUT4_TRIM , RE_CLKOUT3_TRIM , RE_CLKOUT2_TRIM , RE_CLKOUT1_TRIM , RE_CLKOUT0_TRIM }), | |
.CLKOUT_BYPASS ({RE_CLKOUT4_BYPASS, RE_CLKOUT3_BYPASS, RE_CLKOUT2_BYPASS, RE_CLKOUT1_BYPASS, RE_CLKOUT0_BYPASS}), | |
.CLKOUT_CASCADE({CLKOUT4_CASCADE , CLKOUT3_CASCADE , CLKOUT2_CASCADE , CLKOUT1_CASCADE , 1'b0 }), | |
.CLKOUT_DELS ({CLKOUT4_DEL , CLKOUT3_DEL , CLKOUT2_DEL , CLKOUT1_DEL , CLKOUT0_DEL }), | |
.CLKOUT_PHASES ({CLKOUT4_PHASE , CLKOUT3_PHASE , CLKOUT2_PHASE , CLKOUT1_PHASE , CLKOUT0_PHASE }) | |
); | |
`else | |
assign clkout0 = clkin; | |
assign clkout1 = clkin; | |
assign clkout2 = clkin; | |
assign clkout3 = clkin; | |
assign clkout4 = clkin; | |
assign lock = pfden & resetn & clkfb; | |
`endif | |
endmodule | |
`timescale 1ns/10ps | |
module alta_sram ( | |
input WEna, WClk, | |
input [3:0] Din, | |
input [3:0] WAddr, | |
input [3:0] RAddr, | |
output reg [3:0] Dout | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter INIT_VAL = 64'h0; | |
`ifdef ALTA_SIM | |
reg [3:0] mem[15:0]; | |
reg [3:0] init_word; | |
integer i, j; | |
initial | |
begin | |
for ( i = 0; i < 16; i = i + 1) | |
begin | |
for ( j = 0; j < 4; j = j + 1) | |
init_word[j] = INIT_VAL[i * 4 + j]; | |
mem[i] = init_word; | |
end | |
end | |
always @ (RAddr or mem[RAddr]) | |
Dout = mem[RAddr]; | |
always @ (posedge WClk) | |
begin | |
if (WEna) | |
mem[WAddr] <= Din; | |
end | |
`endif | |
endmodule | |
module alta_dpram16x4 ( | |
input WEna, WClk, | |
input [3:0] Din, | |
input [3:0] WAddr, | |
input [3:0] RAddr, | |
output [3:0] Dout); | |
alta_sram dpram_inst( | |
.WEna (WEna ), | |
.WClk (WClk ), | |
.Din (Din ), | |
.WAddr(WAddr), | |
.RAddr(RAddr), | |
.Dout (Dout ) | |
); | |
parameter INIT_VAL = 64'h0; | |
defparam dpram_inst.INIT_VAL = INIT_VAL; | |
endmodule | |
module alta_spram16x4 ( | |
input WEna, WClk, | |
input [3:0] Din, | |
input [3:0] Addr, | |
output [3:0] Dout); | |
alta_sram spram_inst( | |
.WEna (WEna), | |
.WClk (WClk), | |
.Din (Din ), | |
.WAddr(Addr), | |
.RAddr(Addr), | |
.Dout (Dout) | |
); | |
parameter INIT_VAL = 64'h0; | |
defparam spram_inst.INIT_VAL = INIT_VAL; | |
endmodule | |
module alta_wram ( | |
input WEna, WClk, | |
input [7:0] Din, | |
input [3:0] WAddr, | |
input [3:0] RAddr, | |
output reg [7:0] Dout | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter INIT_VAL = 128'h0; | |
`ifdef ALTA_SIM | |
reg [7:0] mem[15:0]; | |
reg [7:0] init_word; | |
integer i, j; | |
initial | |
begin | |
for ( i = 0; i < 16; i = i + 1) | |
begin | |
for ( j = 0; j < 7; j = j + 1) | |
init_word[j] = INIT_VAL[i * 8 + j]; | |
mem[i] = init_word; | |
end | |
end | |
always @ (RAddr or mem[RAddr]) | |
Dout = mem[RAddr]; | |
always @ (posedge WClk) | |
begin | |
if (WEna) | |
mem[WAddr] <= Din; | |
end | |
`endif | |
endmodule | |
module alta_bram_pulse_generator #(parameter PULSE_DELAY = 1) ( | |
input Clk, | |
input Ena, | |
output reg Pulse | |
); | |
parameter PULSE_WIDTH = 1; | |
wire #(PULSE_DELAY) ClkDel = Clk; | |
wire #(PULSE_WIDTH) PulseDel = Pulse; | |
initial Pulse = 1'b0; | |
always @ (posedge ClkDel or posedge PulseDel) begin | |
if (PulseDel) | |
Pulse = 1'b0; | |
else if (Ena && ClkDel) | |
Pulse = 1'b1; | |
end | |
endmodule | |
module alta_bram ( | |
input [17:0] DataInA, DataInB, | |
input [11:0] AddressA, AddressB, | |
output [17:0] DataOutA, DataOutB, | |
input Clk0, ClkEn0, AsyncReset0, | |
input Clk1, ClkEn1, AsyncReset1, | |
input WeRenA, WeRenB | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter CLKMODE = 1'b0; // 0: read/write mode, 1: input/output mode | |
parameter PORTA_WRITEMODE = 1'b0; // 0: normal, 1: read before write | |
parameter PORTB_WRITEMODE = 1'b0; | |
parameter PORTA_WRITETHRU = 1'b0; | |
parameter PORTB_WRITETHRU = 1'b0; | |
parameter PORTB_READONLY = 1'b0; | |
parameter PORTA_OUTREG = 1'b0; | |
parameter PORTB_OUTREG = 1'b0; | |
parameter PORTA_WIDTH = 4'b0; | |
parameter PORTB_WIDTH = 4'b0; | |
parameter INIT_VAL = 4608'b0; | |
localparam NORMAL = 1'b0; | |
localparam READ_BEFORE_WRITE = 1'b1; | |
`ifdef ALTA_SIM | |
reg [17:0] mem [255:0]; | |
reg [17:0] wrDataA, wrDataB, rdDataA, rdDataB; | |
integer i; | |
initial begin | |
for (i = 0; i < 256; i = i + 1) begin | |
mem[i] = INIT_VAL[i*18+17-:18]; | |
end | |
rdDataA = 18'h3FFFF; | |
rdDataB = 18'h3FFFF; | |
end | |
wire clkInt0, clkInt1; | |
alta_clkenctrl clkInt0_inst(.ClkIn(Clk0), .ClkEn(ClkEn0), .ClkOut(clkInt0)); | |
alta_clkenctrl clkInt1_inst(.ClkIn(Clk1), .ClkEn(ClkEn1), .ClkOut(clkInt1)); | |
wire clkInA = CLKMODE ? clkInt0 : clkInt0; | |
wire clkInB = CLKMODE ? clkInt0 : clkInt1; | |
wire clkOutA = CLKMODE ? clkInt1 : clkInt0; | |
wire clkOutB = CLKMODE ? clkInt1 : clkInt1; | |
wire rstInA = CLKMODE ? AsyncReset0 : AsyncReset0; | |
wire rstInB = CLKMODE ? AsyncReset0 : AsyncReset1; | |
wire rstOutA = CLKMODE ? AsyncReset1 : AsyncReset0; | |
wire rstOutB = CLKMODE ? AsyncReset1 : AsyncReset1; | |
wire wrClkA = PORTA_WRITEMODE ? !clkInA : clkInA; | |
wire wrClkB = PORTB_WRITEMODE ? !clkInB : clkInB; | |
wire [17:0] dataInRegA, dataInRegB; | |
wire [11:0] addrInRegA, addrInRegB; | |
wire werenRegA, werenRegB; | |
localparam BUF_DEL = 0; | |
wire [17:0] #BUF_DEL DataInA_buf = DataInA; | |
wire [17:0] #BUF_DEL DataInB_buf = DataInB; | |
wire [11:0] #BUF_DEL AddressA_buf = AddressA; | |
wire [11:0] #BUF_DEL AddressB_buf = AddressB; | |
wire #BUF_DEL WeRenA_buf = WeRenA; | |
wire #BUF_DEL WeRenB_buf = WeRenB; | |
alta_srff addrInRegA_inst[11:0](.Din(AddressA_buf), .Clk(clkInA), .ClkEn(1'b1), .AsyncReset(rstInA), .AsyncPreset(1'b0), .Q(addrInRegA)); | |
alta_srff addrInRegB_inst[11:0](.Din(AddressB_buf), .Clk(clkInB), .ClkEn(1'b1), .AsyncReset(rstInB), .AsyncPreset(1'b0), .Q(addrInRegB)); | |
alta_srff dataInRegA_inst[17:0](.Din(DataInA_buf), .Clk(wrClkA), .ClkEn(1'b1), .AsyncReset(rstInA), .AsyncPreset(1'b0), .Q(dataInRegA)); | |
alta_srff dataInRegB_inst[17:0](.Din(DataInB_buf), .Clk(wrClkB), .ClkEn(1'b1), .AsyncReset(rstInB), .AsyncPreset(1'b0), .Q(dataInRegB)); | |
alta_srff werenRegA_inst (.Din(WeRenA_buf), .Clk(clkInA), .ClkEn(1'b1), .AsyncReset(rstInA), .AsyncPreset(1'b0), .Q(werenRegA)); | |
alta_srff werenRegB_inst (.Din(WeRenB_buf), .Clk(clkInB), .ClkEn(1'b1), .AsyncReset(rstInB), .AsyncPreset(1'b0), .Q(werenRegB)); | |
// Generate read/write pulse | |
wire rdPulseA, rdPulseB, wrPulseA, wrPulseB; | |
alta_bram_pulse_generator genRdPulseA( | |
.Clk(clkInA), | |
.Ena(PORTA_WRITEMODE === NORMAL && !werenRegA || PORTA_WRITEMODE === READ_BEFORE_WRITE), | |
.Pulse(rdPulseA) | |
); | |
alta_bram_pulse_generator genWrPulseA( | |
.Clk(PORTA_WRITEMODE === NORMAL ? clkInA : !clkInA), | |
.Ena(werenRegA), | |
.Pulse(wrPulseA) | |
); | |
alta_bram_pulse_generator genRdPulseB( | |
.Clk(clkInB), | |
.Ena(PORTB_READONLY && werenRegB || !PORTB_READONLY && PORTB_WRITEMODE === NORMAL && !werenRegB || !PORTB_READONLY && PORTB_WRITEMODE === READ_BEFORE_WRITE), | |
.Pulse(rdPulseB) | |
); | |
alta_bram_pulse_generator genWrPulseB( | |
.Clk(PORTB_WRITEMODE === NORMAL ? clkInB : !clkInB), | |
.Ena(!PORTB_READONLY && werenRegB), | |
.Pulse(wrPulseB) | |
); | |
wire [7:0] wordAddrA = addrInRegA[11:4]; | |
wire [7:0] wordAddrB = addrInRegB[11:4]; | |
wire [1:0] byteEnA = addrInRegA[1:0]; | |
wire [1:0] byteEnB = addrInRegB[1:0]; | |
wire [17:0] maskA = PORTA_WIDTH == 4'b0000 ? { {9{byteEnA[1]}}, {9{byteEnA[0]}} } : | |
PORTA_WIDTH == 4'b1000 ? { {9{byteEnA[1] & addrInRegA[3]}}, {9{byteEnA[0] & !addrInRegA[3]}} } : | |
PORTA_WIDTH == 4'b1100 ? (4'b1111 << addrInRegA[3:2]*4+addrInRegA[3]) : | |
PORTA_WIDTH == 4'b1110 ? (2'b11 << addrInRegA[3:1]*2+addrInRegA[3]) : | |
PORTA_WIDTH == 4'b1111 ? (1'b1 << addrInRegA[3:0]*1+addrInRegA[3]) : 18'b0; | |
wire [17:0] maskB = PORTB_WIDTH == 4'b0000 ? { {9{byteEnB[1]}}, {9{byteEnB[0]}} } : | |
PORTB_WIDTH == 4'b1000 ? { {9{byteEnB[1] & addrInRegB[3]}}, {9{byteEnB[0] & !addrInRegB[3]}} } : | |
PORTB_WIDTH == 4'b1100 ? (4'b1111 << addrInRegB[3:2]*4+addrInRegB[3]) : | |
PORTB_WIDTH == 4'b1110 ? (2'b11 << addrInRegB[3:1]*2+addrInRegB[3]) : | |
PORTB_WIDTH == 4'b1111 ? (1'b1 << addrInRegB[3:0]*1+addrInRegB[3]) : 18'b0; | |
always @ (posedge rdPulseA or posedge wrPulseA or posedge rdPulseB or posedge wrPulseB) begin | |
if (wrPulseA) begin | |
wrDataA = mem[wordAddrA]; | |
for (i = 0; i < 18; i = i + 1) begin | |
if (maskA[i]) begin | |
wrDataA[i] = dataInRegA[i]; | |
end | |
end | |
mem[wordAddrA] = wrDataA; | |
if (PORTA_WRITETHRU) begin | |
rdDataA = dataInRegA; | |
end | |
end | |
if (wrPulseB) begin | |
wrDataB = mem[wordAddrB]; | |
for (i = 0; i < 18; i = i + 1) begin | |
if (maskB[i]) begin | |
wrDataB[i] = dataInRegB[i]; | |
end | |
end | |
mem[wordAddrB] = wrDataB; | |
if (PORTB_WRITETHRU) begin | |
rdDataB = dataInRegB; | |
end | |
end | |
if (rdPulseA) begin | |
rdDataA = mem[wordAddrA]; | |
end | |
if (rdPulseB) begin | |
rdDataB = mem[wordAddrB]; | |
end | |
end | |
wire [15:0] rdDataA_x16 = { rdDataA[16:9], rdDataA[7:0] }; | |
wire [8:0] rdDataA_x9 = addrInRegA[3] ? rdDataA[17:9] : rdDataA[8:0]; | |
wire [3:0] rdDataA_x4 = rdDataA_x16 >> addrInRegA[3:2]*4; | |
wire [1:0] rdDataA_x2 = rdDataA_x16 >> addrInRegA[3:1]*2; | |
wire rdDataA_x1 = rdDataA_x16 >> addrInRegA[3:0]; | |
wire [17:0] dataOutSelA = PORTA_WIDTH == 4'b0000 ? rdDataA : | |
PORTA_WIDTH == 4'b1000 ? { 1'b1, rdDataA_x9[7:0], 1'b1, rdDataA_x9[8], 7'h7f } : | |
PORTA_WIDTH == 4'b1100 ? { 11'h7FF , rdDataA_x4, 3'b111 } : | |
PORTA_WIDTH == 4'b1110 ? { 15'h7FFF , rdDataA_x2, 1'b1 } : | |
PORTA_WIDTH == 4'b1111 ? { 17'h1FFFF, rdDataA_x1 } : 18'bx; | |
wire [15:0] rdDataB_x16 = { rdDataB[16:9], rdDataB[7:0] }; | |
wire [8:0] rdDataB_x9 = addrInRegB[3] ? rdDataB[17:9] : rdDataB[8:0]; | |
wire [3:0] rdDataB_x4 = rdDataB_x16 >> addrInRegB[3:2]*4; | |
wire [1:0] rdDataB_x2 = rdDataB_x16 >> addrInRegB[3:1]*2; | |
wire rdDataB_x1 = rdDataB_x16 >> addrInRegB[3:0]; | |
wire [17:0] dataOutSelB = PORTB_WIDTH == 4'b0000 ? rdDataB : | |
PORTB_WIDTH == 4'b1000 ? { 1'b1, rdDataB_x9[7:0], 1'b1, rdDataB_x9[8], 7'h7f } : | |
PORTB_WIDTH == 4'b1100 ? { 11'h7FF , rdDataB_x4, 3'b111 } : | |
PORTB_WIDTH == 4'b1110 ? { 15'h7FFF , rdDataB_x2, 1'b1 } : | |
PORTB_WIDTH == 4'b1111 ? { 17'h1FFFF, rdDataB_x1 } : 18'bx; | |
wire [17:0] dataOutRegA, dataOutRegB; | |
alta_srff dataOutRegA_inst[17:0](.Din(dataOutSelA), .Clk(clkOutA), .ClkEn(1'b1), .AsyncReset(rstOutA), .AsyncPreset(1'b0), .Q(dataOutRegA)); | |
alta_srff dataOutRegB_inst[17:0](.Din(dataOutSelB), .Clk(clkOutB), .ClkEn(1'b1), .AsyncReset(rstOutB), .AsyncPreset(1'b0), .Q(dataOutRegB)); | |
assign DataOutA = PORTA_OUTREG ? dataOutRegA : dataOutSelA; | |
assign DataOutB = PORTB_OUTREG ? dataOutRegB : dataOutSelB; | |
`endif | |
endmodule | |
module alta_ram4k #(parameter DATA_WIDTH_A = 18, | |
ADDR_WIDTH_A = 8, | |
BYTE_WIDTH_A = 2, | |
DATA_WIDTH_B = 0, | |
ADDR_WIDTH_B = 0, | |
BYTE_WIDTH_B = 0, | |
INIT_VAL = 4608'b0, | |
CLKMODE = "read_write", | |
PORTA_WRITEMODE = "normal", | |
PORTB_WRITEMODE = "normal", | |
PORTB_READONLY = "no", | |
PORTA_OUTREG = "no", | |
PORTB_OUTREG = "no", | |
INIT_PORT = "a") ( | |
input [DATA_WIDTH_A-1:0] DataInA, | |
input [DATA_WIDTH_B-1:0] DataInB, | |
output [DATA_WIDTH_A-1:0] DataOutA, | |
output [DATA_WIDTH_B-1:0] DataOutB, | |
input [ADDR_WIDTH_A-1:0] AddressA, | |
input [ADDR_WIDTH_B-1:0] AddressB, | |
input [BYTE_WIDTH_A-1:0] ByteEnA, | |
input [BYTE_WIDTH_B-1:0] ByteEnB, | |
input Clk0, ClkEn0, AsyncReset0, | |
input Clk1, ClkEn1, AsyncReset1, | |
input WeRenA, WeRenB | |
); | |
initial | |
begin | |
validate(DATA_WIDTH_A, ADDR_WIDTH_A, BYTE_WIDTH_A); | |
validate(DATA_WIDTH_B, ADDR_WIDTH_B, BYTE_WIDTH_B); | |
end | |
localparam isSinglePort = DATA_WIDTH_A > 18; | |
wire portClk0 = Clk0; | |
wire portClk1 = isSinglePort ? Clk0 : Clk1; | |
wire portClkEn0 = ClkEn0; | |
wire portClkEn1 = isSinglePort ? ClkEn0 : ClkEn1; | |
wire portAsyncReset0 = AsyncReset0; | |
wire portAsyncReset1 = isSinglePort ? AsyncReset0 : AsyncReset1; | |
wire portWeRenA = WeRenA; | |
wire portWeRenB = isSinglePort ? WeRenA : WeRenB; | |
wire [17:0] portDataInA = portDataIn(DATA_WIDTH_A, DataInA, DataInA[(DATA_WIDTH_A+1)/2-1:0]); | |
wire [17:0] portDataInB = portDataIn(DATA_WIDTH_B, DataInB, DataInA[DATA_WIDTH_A-1:DATA_WIDTH_A/2]); | |
wire [11:0] portAddressA = portAddr(ADDR_WIDTH_A, AddressA, BYTE_WIDTH_A, ByteEnA, 1'b0, AddressA, ByteEnA); | |
wire [11:0] portAddressB = portAddr(ADDR_WIDTH_B, AddressB, BYTE_WIDTH_B, ByteEnB, 1'b1, AddressA, ByteEnA); | |
wire [17:0] portDataOutA, portDataOutB; | |
assign DataOutA = portDataOut(DATA_WIDTH_A, portDataOutA, portDataOutB); | |
assign DataOutB = portDataOut(DATA_WIDTH_B, portDataOutB, portDataOutB); | |
alta_bram ram_inst ( | |
.DataInA(portDataInA), .DataInB(portDataInB), | |
.AddressA(portAddressA), .AddressB(portAddressB), | |
.DataOutA(portDataOutA), .DataOutB(portDataOutB), | |
.Clk0(portClk0), .ClkEn0(portClkEn0), .AsyncReset0(portAsyncReset0), | |
.Clk1(portClk1), .ClkEn1(portClkEn1), .AsyncReset1(portAsyncReset1), | |
.WeRenA(portWeRenA), .WeRenB(portWeRenB) | |
); | |
defparam ram_inst.PORTA_WIDTH = portCfg(DATA_WIDTH_A); | |
defparam ram_inst.PORTB_WIDTH = portCfg(DATA_WIDTH_B); | |
defparam ram_inst.CLKMODE = (CLKMODE == "read_write" ? 1'b0 : (CLKMODE == "input_output" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_READONLY = (PORTB_READONLY == "no" ? 1'b0 : (PORTB_READONLY == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_OUTREG = (PORTA_OUTREG == "no" ? 1'b0 : (PORTA_OUTREG == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_OUTREG = (PORTB_OUTREG == "no" ? 1'b0 : (PORTB_OUTREG == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_WRITEMODE = (PORTA_WRITEMODE == "normal" || PORTA_WRITEMODE == "write_thru" ? 1'b0 : (PORTA_WRITEMODE == "read_before_write" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_WRITEMODE = (PORTB_WRITEMODE == "normal" || PORTB_WRITEMODE == "write_thru" ? 1'b0 : (PORTB_WRITEMODE == "read_before_write" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_WRITETHRU = (PORTA_WRITEMODE == "normal" || PORTA_WRITEMODE == "read_before_write" ? 1'b0 : (PORTA_WRITEMODE == "write_thru" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_WRITETHRU = (PORTB_WRITEMODE == "normal" || PORTB_WRITEMODE == "read_before_write" ? 1'b0 : (PORTB_WRITEMODE == "write_thru" ? 1'b1 : 1'bx)); | |
defparam ram_inst.INIT_VAL = (INIT_PORT == "a" ? portInitVal(DATA_WIDTH_A, INIT_VAL) : INIT_PORT == "b" ? portInitVal(DATA_WIDTH_B, INIT_VAL) : 4608'b0); | |
task validate(input integer data_width, input integer addr_width, input integer byte_width); | |
reg error; | |
begin | |
error = 1'b0; | |
case (data_width) | |
36, 32: if (addr_width > 7 || byte_width != 4) error = 1'b1; // This is only supported in single port | |
18, 16: if (addr_width > 8 || byte_width != 2) error = 1'b1; | |
9, 8: if (addr_width > 9 || byte_width != 1) error = 1'b1; | |
4: if (addr_width > 10 || byte_width != 0) error = 1'b1; | |
2: if (addr_width > 11 || byte_width != 0) error = 1'b1; | |
1: if (addr_width > 12 || byte_width != 0) error = 1'b1; | |
0: error = 1'b0; // port not used | |
default: $display("Illegal data width %0d specified", data_width); | |
endcase | |
if (error) | |
$display("Illegal data/address/byte enable width sepcified: %0d/%0d/%0d", data_width, addr_width, byte_width); | |
if (addr_width < 7) | |
$display("Illegal address width %0d specified", addr_width); | |
end | |
endtask | |
function [3:0] portCfg(input integer data_width); | |
begin | |
case (data_width) | |
36, 32: portCfg = 4'b0000; | |
18, 16: portCfg = 4'b0000; | |
9, 8: portCfg = 4'b1000; | |
4: portCfg = 4'b1100; | |
2: portCfg = 4'b1110; | |
1: portCfg = 4'b1111; | |
0: portCfg = 4'b0000; | |
endcase | |
end | |
endfunction | |
function [4607:0] portInitVal(input integer data_width, input [4607:0] initVal); | |
begin : initval | |
integer i; | |
case (data_width) | |
36, 18, 9: | |
portInitVal = initVal; | |
32, 16, 8, 4, 2, 1: | |
for (i = 0; i < 256; i = i + 1) | |
portInitVal[i*18+17-:18] = { 1'b0, initVal[i*16+15-:8], 1'b0, initVal[i*16+7-:8] }; | |
0: | |
portInitVal = 4608'b0; | |
endcase | |
end | |
endfunction | |
function [17:0] portDataIn(input integer data_width, input [17:0] data, input [17:0] data0); | |
begin | |
case (data_width) | |
36: portDataIn = data0[17:0]; | |
32: portDataIn = { 1'b1, data0[15:8], 1'b1, data0[7:0] }; | |
18: portDataIn = data[17:0]; | |
16: portDataIn = { 1'b1, data[15:8], 1'b1, data[7:0] }; | |
9: portDataIn = { 2{ data[8:0] } }; | |
8: portDataIn = { 2{ 1'b1, data[7:0] } }; | |
4: portDataIn = { 2{ 1'b1, { 2{ data[3:0] } } } }; | |
2: portDataIn = { 2{ 1'b1, { 4{ data[1:0] } } } }; | |
1: portDataIn = { 2{ 1'b1, { 8{ data[0:0] } } } }; | |
0: portDataIn = ~18'b0; | |
endcase | |
end | |
endfunction | |
function [11:0] portAddr(input integer addr_width, input [11:0] addr, input integer byte_width, input [1:0] byteEn, input portId, input [6:0] addr0, input [3:0] byteEn0); | |
begin | |
case (addr_width) | |
12: portAddr = addr; | |
11: portAddr = { addr[10:0], 1'b1 }; | |
10: portAddr = { addr[ 9:0], 2'b11 }; | |
9: portAddr = { addr[ 8:0], 3'b111 }; // Data width 8 or 9, default byte enable is 2'b11 | |
8: portAddr = { addr[ 7:0], 4'b1111 }; // Data width 16 or 18, default byte enable is 2'b11 | |
7: portAddr = { { addr0, portId }, 4'b1111 }; // Data width 32 or 36, lsb is 0/1 depends on port | |
0: portAddr = ~12'b0; | |
endcase | |
case (byte_width) | |
4: portAddr[1:0] = byteEn0[(portId+1)*2-1-:2]; | |
2: portAddr[1:0] = byteEn; | |
1: portAddr[1:0] = { 2{ byteEn[0] } }; | |
endcase | |
end | |
endfunction | |
function [35:0] portDataOut(input integer data_width, input [17:0] data, input [17:0] data0); | |
begin | |
case (data_width) | |
36: portDataOut = { data0, data }; | |
32: portDataOut = { data0[16:9], data0[7:0], data[16:9], data[7:0] }; | |
18: portDataOut = data; | |
16: portDataOut = { data[16:9], data[7:0] }; | |
9: portDataOut = { data[7], data[16:9] }; | |
8: portDataOut = data[16:9]; | |
4: portDataOut = data[ 6:3]; | |
2: portDataOut = data[ 2:1]; | |
1: portDataOut = data[ 0:0]; | |
0: portDataOut = 36'b0; | |
endcase | |
end | |
endfunction | |
endmodule | |
module alta_boot ( | |
input i_boot, | |
input [1:0] im_vector_sel, | |
input i_osc_enb, | |
output o_osc | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
`ifdef ALTA_SIM | |
`endif | |
endmodule | |
`timescale 1ns/10ps | |
module alta_osc ( | |
input i_osc_enb, | |
output o_osc | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter OSC_DEL = 20; | |
`ifdef ALTA_SIM | |
reg osc_reg = 1'b0; | |
always #OSC_DEL if (i_osc_enb == 1'b0) osc_reg = !osc_reg; | |
assign o_osc = osc_reg; | |
`endif | |
endmodule | |
module alta_ufml ( | |
input ufm_csn, ufm_sck, ufm_sdi, | |
output ufm_sdo | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
endmodule | |
module alta_jtag ( | |
input tdouser, | |
output usr1user, runidleuser, updateuser, clkdruser, shiftuser, tdiutap, tckutap, tmsutap | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
endmodule | |
`ifdef ALTA_SIM | |
module alta_mult_int #(parameter DATA_WIDTH_A = 9, DATA_WIDTH_B = 9) ( | |
input [DATA_WIDTH_A-1:0] DataInA, | |
input [DATA_WIDTH_B-1:0] DataInB, | |
input SignA, SignB, Enable, | |
output [DATA_WIDTH_A+DATA_WIDTH_B-1:0] DataOut | |
); | |
parameter DATAOUT_WIDTH = DATA_WIDTH_A + DATA_WIDTH_B; | |
wire [DATA_WIDTH_A-1:0] DataInA_buf = Enable ? DataInA : {DATA_WIDTH_A{1'b0}}; | |
wire [DATA_WIDTH_B-1:0] DataInB_buf = Enable ? DataInB : {DATA_WIDTH_B{1'b0}}; | |
wire isNegDataA = SignA & DataInA_buf[DATA_WIDTH_A-1]; | |
wire isNegDataB = SignB & DataInB_buf[DATA_WIDTH_B-1]; | |
wire [DATAOUT_WIDTH-1:0] DataInA_comp = isNegDataA ? -{ {DATA_WIDTH_B{1'b1}}, DataInA_buf } : DataInA_buf; | |
wire [DATAOUT_WIDTH-1:0] DataInB_comp = isNegDataB ? -{ {DATA_WIDTH_A{1'b1}}, DataInB_buf } : DataInB_buf; | |
wire [DATAOUT_WIDTH-1:0] DataOut_comp = DataInA_comp * DataInB_comp; | |
assign DataOut = (isNegDataA ^ isNegDataB) ? -DataOut_comp : DataOut_comp; | |
endmodule | |
`endif | |
module alta_mult ( | |
input Clk, ClkEn, AsyncReset, | |
input SignA, SignB, | |
input [8:0] DataInA0, DataInB0, DataInA1, DataInB1, | |
output [17:0] DataOut0, DataOut1 | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter MULT_MODE = 1'b0; // 0: 18x18, 1: 9x9 | |
parameter PORTA_INREG0 = 1'b0; | |
parameter PORTA_INREG1 = 1'b0; | |
parameter PORTB_INREG0 = 1'b0; | |
parameter PORTB_INREG1 = 1'b0; | |
parameter SIGNA_REG = 1'b0; | |
parameter SIGNB_REG = 1'b0; | |
parameter OUTREG0 = 1'b0; | |
parameter OUTREG1 = 1'b0; | |
`ifdef ALTA_SIM | |
alta_clkenctrl_rst clkInt_inst(.ClkIn(Clk), .ClkEn(ClkEn), .ClkOut(clkInt), .Rst(AsyncReset)); | |
wire [8:0] dataInRegA0, dataInRegB0, dataInRegA1, dataInRegB1; | |
alta_dff dataInRegA0_inst[8:0] (.Din(DataInA0), .Clk(clkInt & PORTA_INREG0), .AsyncReset(AsyncReset), .Q(dataInRegA0)); | |
alta_dff dataInRegA1_inst[8:0] (.Din(DataInA1), .Clk(clkInt & PORTA_INREG1), .AsyncReset(AsyncReset), .Q(dataInRegA1)); | |
alta_dff dataInRegB0_inst[8:0] (.Din(DataInB0), .Clk(clkInt & PORTB_INREG0), .AsyncReset(AsyncReset), .Q(dataInRegB0)); | |
alta_dff dataInRegB1_inst[8:0] (.Din(DataInB1), .Clk(clkInt & PORTB_INREG1), .AsyncReset(AsyncReset), .Q(dataInRegB1)); | |
alta_dff signRegA_inst (.Din(SignA), .Clk(clkInt & SIGNA_REG), .AsyncReset(AsyncReset), .Q(signRegA)); | |
alta_dff signRegB_inst (.Din(SignB), .Clk(clkInt & SIGNB_REG), .AsyncReset(AsyncReset), .Q(signRegB)); | |
wire [17:0] dataInA_int = {PORTA_INREG1 ? dataInRegA1 : DataInA1, PORTA_INREG0 ? dataInRegA0: DataInA0}; | |
wire [17:0] dataInB_int = {PORTB_INREG1 ? dataInRegB1 : DataInB1, PORTB_INREG0 ? dataInRegB0: DataInB0}; | |
wire signA_int = SIGNA_REG ? signRegA : SignA; | |
wire signB_int = SIGNB_REG ? signRegB : SignB; | |
wire [17:0] dataOutX9_0, dataOutX9_1; | |
wire [35:0] dataOutX18; | |
alta_mult_int #(.DATA_WIDTH_A(9), .DATA_WIDTH_B(9)) mult9_0 ( | |
.DataInA(dataInA_int[8:0]), | |
.DataInB(dataInB_int[8:0]), | |
.SignA(signA_int), | |
.SignB(signB_int), | |
.Enable(MULT_MODE), | |
.DataOut(dataOutX9_0) | |
); | |
alta_mult_int #(.DATA_WIDTH_A(9), .DATA_WIDTH_B(9)) mult9_1 ( | |
.DataInA(dataInA_int[17:9]), | |
.DataInB(dataInB_int[17:9]), | |
.SignA(signA_int), | |
.SignB(signB_int), | |
.Enable(MULT_MODE), | |
.DataOut(dataOutX9_1) | |
); | |
alta_mult_int #(.DATA_WIDTH_A(18), .DATA_WIDTH_B(18)) mult18 ( | |
.DataInA(dataInA_int), | |
.DataInB(dataInB_int), | |
.SignA(signA_int), | |
.SignB(signB_int), | |
.Enable(!MULT_MODE), | |
.DataOut(dataOutX18) | |
); | |
wire [35:0] dataOutInt = MULT_MODE ? { dataOutX9_1, dataOutX9_0 } : dataOutX18; | |
wire [35:0] dataOutReg; | |
alta_dff dataOutReg0[17:0] (.Din(dataOutInt[17:0] ), .Clk(clkInt & OUTREG0), .AsyncReset(AsyncReset), .Q(dataOutReg[17:0] )); | |
alta_dff dataOutReg1[17:0] (.Din(dataOutInt[35:18]), .Clk(clkInt & OUTREG1), .AsyncReset(AsyncReset), .Q(dataOutReg[35:18])); | |
assign DataOut0 = OUTREG0 ? dataOutReg[17:0] : dataOutInt[17:0] ; | |
assign DataOut1 = OUTREG1 ? dataOutReg[35:18] : dataOutInt[35:18]; | |
`endif | |
endmodule | |
module alta_dff_en ( | |
input Din, Clk, AsyncReset, En, | |
output Q | |
); | |
alta_dff dff_inst (.Din(Din), .Clk(Clk), .AsyncReset(AsyncReset), .Q(dffOut)); | |
assign Q = En ? dffOut : Din; | |
endmodule | |
module alta_multm_add ( | |
input [17:0] DataIn0, DataIn1, | |
input [35:0] AccuIn, DataCin, | |
input [35:0] MultData0, MultData1, MultData2, | |
input Sign, AddSub0, AddSub1, X18Mode, X9Mode, | |
input [1:0] AccuMode, // 00: Load, 01: Accu, 10: Cin, 11: Hold | |
output [35:0] DataOut | |
); | |
wire [35:0] DataIn0_comp = {{18{Sign & DataIn0[17]}}, DataIn0}; | |
wire [35:0] DataIn1_comp = {{18{Sign & DataIn1[17]}}, DataIn1}; | |
wire [35:0] data0 = (X18Mode | X9Mode) ? MultData0 : AccuMode[0] ? AccuIn : AccuMode[1] ? DataCin : 36'b0; | |
wire [35:0] data1 = X18Mode ? MultData1 : (X9Mode | AccuMode[1]) ? 36'b0 : DataIn0_comp; | |
wire [35:0] data2 = X18Mode ? MultData2 : (X9Mode | AccuMode[1]) ? 36'b0 : DataIn1_comp; | |
wire [35:0] data1_int = AddSub0 ? (~data1 + 1) : data1; | |
wire [35:0] data2_int = AddSub1 ? (~data2 + 1) : data2; | |
assign DataOut = data0 + data1_int + data2_int; | |
endmodule | |
module alta_multm ( | |
input Clk0, ClkEn0, AsyncReset0, | |
input Clk1, ClkEn1, AsyncReset1, | |
input SignA, SignB, SignW, | |
input InModeA, InModeB, InModeW, | |
input AddSub0, AddSub1, | |
input [1:0] OpMode, | |
input [1:0] OutMode, | |
input [8:0] DataInA0, DataInA1, DataCinA0, DataCinA1, | |
input [8:0] DataInB0, DataInB1, DataCinB0, DataCinB1, | |
input [8:0] DataInW0, DataInW1, DataCinW0, DataCinW1, | |
output [8:0] DataCoutA0, DataCoutA1, | |
output [8:0] DataCoutB0, DataCoutB1, | |
output [8:0] DataCoutW0, DataCoutW1, | |
input [35:0] DataOutCin0, DataOutCin1, | |
output [35:0] DataOutCout0, DataOutCout1, | |
output [17:0] DataOut0, DataOut1 | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter MULT_MODE = 2'b0; // 0: 18x18, 1: 9x9, 2: 9x9 + accu | |
parameter PORTA_ASYNC = 1'b0; | |
parameter PORTB_ASYNC = 1'b0; | |
parameter PORTW_ASYNC = 1'b0; | |
parameter SIGNA_ASYNC = 1'b0; | |
parameter SIGNB_ASYNC = 1'b0; | |
parameter SIGNW_ASYNC = 1'b0; | |
parameter ADDSUB0_ASYNC = 1'b0; | |
parameter ADDSUB1_ASYNC = 1'b0; | |
parameter OPMODE_ASYNC = 1'b0; | |
parameter MULTA_ASYNC = 1'b0; | |
parameter MULTB_ASYNC = 1'b0; | |
parameter ACCUA_ASYNC = 1'b0; | |
parameter ACCUB_ASYNC = 1'b0; | |
parameter OUT0_ASYNC = 1'b0; | |
parameter OUT1_ASYNC = 1'b0; | |
parameter PORTA0_CLK = 2'b0; // 2'b00: No clock, 2'b01: Clk0, 2'b10, Clk1 | |
parameter PORTA1_CLK = 2'b0; | |
parameter PORTB0_CLK = 2'b0; | |
parameter PORTB1_CLK = 2'b0; | |
parameter PORTW0_CLK = 2'b0; | |
parameter PORTW1_CLK = 2'b0; | |
parameter SIGNA_CLK = 2'b0; | |
parameter SIGNB_CLK = 2'b0; | |
parameter SIGNW_CLK = 2'b0; | |
parameter ADDSUB0_CLK = 2'b0; | |
parameter ADDSUB1_CLK = 2'b0; | |
parameter OPMODE_CLK = 2'b0; | |
parameter MULTA_CLK = 2'b0; | |
parameter MULTB_CLK = 2'b0; | |
parameter ACCUA_CLK = 2'b0; | |
parameter ACCUB_CLK = 2'b0; | |
parameter OUT0_CLK = 2'b0; | |
parameter OUT1_CLK = 2'b0; | |
`ifdef ALTA_SIM | |
wire [2:0] clkInt; | |
assign clkInt[0] = 1'b0; | |
alta_clkenctrl clkInt0_inst(.ClkIn(Clk0), .ClkEn(ClkEn0), .ClkOut(clkInt[1])); | |
alta_clkenctrl clkInt1_inst(.ClkIn(Clk1), .ClkEn(ClkEn1), .ClkOut(clkInt[2])); | |
wire porta0Clk = clkInt[PORTA0_CLK]; | |
wire porta1Clk = clkInt[PORTA1_CLK]; | |
wire portb0Clk = clkInt[PORTB0_CLK]; | |
wire portb1Clk = clkInt[PORTB1_CLK]; | |
wire portw0Clk = clkInt[PORTW0_CLK]; | |
wire portw1Clk = clkInt[PORTW1_CLK]; | |
wire signaClk = clkInt[SIGNA_CLK]; | |
wire signbClk = clkInt[SIGNB_CLK]; | |
wire signwClk = clkInt[SIGNW_CLK]; | |
wire addsub0Clk = clkInt[ADDSUB0_CLK]; | |
wire addsub1Clk = clkInt[ADDSUB1_CLK]; | |
wire opmodeClk = clkInt[OPMODE_CLK]; | |
wire [1:0] asyncInt = { AsyncReset1, AsyncReset0 }; | |
wire portaAsync = asyncInt[PORTA_ASYNC]; | |
wire portbAsync = asyncInt[PORTB_ASYNC]; | |
wire portwAsync = asyncInt[PORTW_ASYNC]; | |
wire signaAsync = asyncInt[SIGNA_ASYNC]; | |
wire signbAsync = asyncInt[SIGNB_ASYNC]; | |
wire signwAsync = asyncInt[SIGNW_ASYNC]; | |
wire addsub0Async = asyncInt[ADDSUB0_ASYNC]; | |
wire addsub1Async = asyncInt[ADDSUB1_ASYNC]; | |
wire opmodeAsync = asyncInt[OPMODE_ASYNC]; | |
wire [8:0] dataInA0_int, dataInA1_int, dataInB0_int, dataInB1_int, dataInW0_int, dataInW1_int; | |
alta_dff_en dataInRegA0[8:0] (.Din(InModeA ? DataCinA0 : DataInA0), .Clk(porta0Clk), .AsyncReset(portaAsync), .En(|PORTA0_CLK), .Q(dataInA0_int)); | |
alta_dff_en dataInRegA1[8:0] (.Din(InModeA ? DataCinA1 : DataInA1), .Clk(porta1Clk), .AsyncReset(portaAsync), .En(|PORTA1_CLK), .Q(dataInA1_int)); | |
alta_dff_en dataInRegB0[8:0] (.Din(InModeB ? DataCinB0 : DataInB0), .Clk(portb0Clk), .AsyncReset(portbAsync), .En(|PORTB0_CLK), .Q(dataInB0_int)); | |
alta_dff_en dataInRegB1[8:0] (.Din(InModeB ? DataCinB1 : DataInB1), .Clk(portb1Clk), .AsyncReset(portbAsync), .En(|PORTB1_CLK), .Q(dataInB1_int)); | |
alta_dff_en dataInRegW0[8:0] (.Din(InModeW ? DataCinW0 : DataInW0), .Clk(portw0Clk), .AsyncReset(portwAsync), .En(|PORTW0_CLK), .Q(dataInW0_int)); | |
alta_dff_en dataInRegW1[8:0] (.Din(InModeW ? DataCinW1 : DataInW1), .Clk(portw1Clk), .AsyncReset(portwAsync), .En(|PORTW1_CLK), .Q(dataInW1_int)); | |
assign DataCoutA0 = dataInA0_int; | |
assign DataCoutA1 = dataInA1_int; | |
assign DataCoutB0 = dataInB0_int; | |
assign DataCoutB1 = dataInB1_int; | |
assign DataCoutW0 = dataInW0_int; | |
assign DataCoutW1 = dataInW1_int; | |
alta_dff_en signRegA (.Din(SignA), .Clk(signaClk), .AsyncReset(signaAsync), .En(|SIGNA_CLK), .Q(signA_int)); | |
alta_dff_en signRegB (.Din(SignB), .Clk(signbClk), .AsyncReset(signbAsync), .En(|SIGNB_CLK), .Q(signB_int)); | |
alta_dff_en signRegW (.Din(SignW), .Clk(signwClk), .AsyncReset(signwAsync), .En(|SIGNW_CLK), .Q(signW_int)); | |
wire x18_mode = (MULT_MODE == 2'b00); | |
wire x9_mode = (MULT_MODE == 2'b01); | |
wire accu_mode = (MULT_MODE[1] == 1'b1); | |
wire [1:0] opmode_int; | |
alta_dff_en addsubRegA0 (.Din(AddSub0), .Clk(addsub0Clk), .AsyncReset(addsub0Async), .En(|ADDSUB0_CLK), .Q(addsubA0_int)); | |
alta_dff_en addsubRegA1 (.Din(AddSub1), .Clk(addsub1Clk), .AsyncReset(addsub1Async), .En(|ADDSUB1_CLK), .Q(addsubA1_int)); | |
alta_dff_en addsubRegB0 (.Din(AddSub0), .Clk(addsub0Clk), .AsyncReset(addsub0Async), .En(|ADDSUB0_CLK), .Q(addsubB0_int)); | |
alta_dff_en addsubRegB1 (.Din(AddSub1), .Clk(addsub1Clk), .AsyncReset(addsub1Async), .En(|ADDSUB1_CLK), .Q(addsubB1_int)); | |
alta_dff_en opmodeReg[1:0] (.Din(OpMode), .Clk(opmodeClk), .AsyncReset(opmodeAsync), .En(|OPMODE_CLK), .Q(opmode_int)); | |
wire [17:0] multOutX9_A0, multOutX9_A1; | |
wire [17:0] multOutX9_B0, multOutX9_B1; | |
alta_mult_int #(.DATA_WIDTH_A(9), .DATA_WIDTH_B(9)) mult9_A0 ( | |
.DataInA(dataInA0_int), | |
.DataInB(dataInW0_int), | |
.SignA(signA_int & !x18_mode), | |
.SignB(signW_int & !x18_mode), | |
.Enable(1'b1), | |
.DataOut(multOutX9_A0) | |
); | |
alta_mult_int #(.DATA_WIDTH_A(9), .DATA_WIDTH_B(9)) mult9_A1 ( | |
.DataInA(dataInA1_int), | |
.DataInB(dataInW1_int), | |
.SignA(signA_int & !x18_mode), | |
.SignB(signW_int), | |
.Enable(1'b1), | |
.DataOut(multOutX9_A1) | |
); | |
alta_mult_int #(.DATA_WIDTH_A(9), .DATA_WIDTH_B(9)) mult9_B0 ( | |
.DataInA(dataInB0_int), | |
.DataInB(dataInW0_int), | |
.SignA(signB_int), | |
.SignB(signW_int & !x18_mode), | |
.Enable(1'b1), | |
.DataOut(multOutX9_B0) | |
); | |
alta_mult_int #(.DATA_WIDTH_A(9), .DATA_WIDTH_B(9)) mult9_B1 ( | |
.DataInA(dataInB1_int), | |
.DataInB(dataInW1_int), | |
.SignA(signB_int), | |
.SignB(signW_int), | |
.Enable(1'b1), | |
.DataOut(multOutX9_B1) | |
); | |
wire multaClk = clkInt[MULTA_CLK]; | |
wire multbClk = clkInt[MULTB_CLK]; | |
wire multaAsync = asyncInt[MULTA_ASYNC]; | |
wire multbAsync = asyncInt[MULTB_ASYNC]; | |
wire [17:0] multA0_int, multA1_int, multB0_int, multB1_int; | |
alta_dff_en multRegA0[17:0] (.Din(multOutX9_A0), .Clk(multaClk), .AsyncReset(multaAsync), .En(|MULTA_CLK), .Q(multA0_int)); | |
alta_dff_en multRegA1[17:0] (.Din(multOutX9_A1), .Clk(multaClk), .AsyncReset(multaAsync), .En(|MULTA_CLK), .Q(multA1_int)); | |
alta_dff_en multRegB0[17:0] (.Din(multOutX9_B0), .Clk(multbClk), .AsyncReset(multbAsync), .En(|MULTB_CLK), .Q(multB0_int)); | |
alta_dff_en multRegB1[17:0] (.Din(multOutX9_B1), .Clk(multbClk), .AsyncReset(multbAsync), .En(|MULTB_CLK), .Q(multB1_int)); | |
alta_dff_en multSignRegA (.Din(signA_int|signW_int), .Clk(multaClk), .AsyncReset(multaAsync), .En(|MULTA_CLK), .Q(multSignA)); | |
alta_dff_en multSignRegB (.Din(signB_int|signW_int), .Clk(multbClk), .AsyncReset(multbAsync), .En(|MULTB_CLK), .Q(multSignB)); | |
alta_dff_en multAddSubRegA0 (.Din(addsubA0_int), .Clk(multaClk), .AsyncReset(multaAsync), .En(|MULTA_CLK), .Q(multAddSubA0)); | |
alta_dff_en multAddSubRegA1 (.Din(addsubA1_int), .Clk(multaClk), .AsyncReset(multaAsync), .En(|MULTA_CLK), .Q(multAddSubA1)); | |
alta_dff_en multAddSubRegB0 (.Din(addsubB0_int), .Clk(multbClk), .AsyncReset(multbAsync), .En(|MULTB_CLK), .Q(multAddSubB0)); | |
alta_dff_en multAddSubRegB1 (.Din(addsubB1_int), .Clk(multbClk), .AsyncReset(multbAsync), .En(|MULTB_CLK), .Q(multAddSubB1)); | |
wire [1:0] multOpModeA, multOpModeB; | |
alta_dff_en multOpModeRegA[1:0] (.Din(opmode_int), .Clk(multaClk), .AsyncReset(multaAsync), .En(|MULTA_CLK), .Q(multOpModeA)); | |
alta_dff_en multOpModeRegB[1:0] (.Din(opmode_int), .Clk(multbClk), .AsyncReset(multbAsync), .En(|MULTB_CLK), .Q(multOpModeB)); | |
wire [35:0] accua_int, accub_int; | |
wire [35:0] accua_out, accub_out; | |
wire [35:0] mult_data0 = {multOutX9_B1, multOutX9_A0}; | |
wire [35:0] mult_data1 = {{9{signW_int & multOutX9_A1[17]}}, multOutX9_A1, 9'b0 }; | |
wire [35:0] mult_data2 = {{9{signB_int & multOutX9_B0[17]}}, multOutX9_B0, 9'b0 }; | |
wire [35:0] mult_data3 = {multOutX9_B0, multOutX9_A1}; | |
alta_multm_add accua_inst ( | |
.DataIn0(multA0_int), | |
.DataIn1(multA1_int), | |
.AccuIn(accua_int), | |
.DataCin(DataOutCin0), | |
.MultData0(mult_data0), | |
.MultData1(mult_data1), | |
.MultData2(mult_data2), | |
.Sign(multSignA), | |
.AddSub0(multAddSubA0), | |
.AddSub1(multAddSubA1), | |
.X18Mode(x18_mode), | |
.X9Mode(x9_mode), | |
.AccuMode(multOpModeA), | |
.DataOut(accua_out) | |
); | |
alta_multm_add accub_inst ( | |
.DataIn0(multB0_int), | |
.DataIn1(multB1_int), | |
.AccuIn(accub_int), | |
.DataCin(DataOutCin1), | |
.MultData0(mult_data3), | |
.MultData1(36'b0), | |
.MultData2(36'b0), | |
.Sign(multSignB), | |
.AddSub0(multAddSubB0), | |
.AddSub1(multAddSubB1), | |
.X18Mode(x18_mode), | |
.X9Mode(x9_mode), | |
.AccuMode(multOpModeB), | |
.DataOut(accub_out) | |
); | |
wire accuaClk = clkInt[ACCUA_CLK]; | |
wire accubClk = clkInt[ACCUB_CLK]; | |
wire accuaAsync = asyncInt[ACCUA_ASYNC]; | |
wire accubAsync = asyncInt[ACCUB_ASYNC]; | |
alta_dff_en accuReg0[35:0] (.Din(accua_out), .Clk(accuaClk), .AsyncReset(accuaAsync), .En(|ACCUA_CLK), .Q(accua_int)); | |
alta_dff_en accuReg1[35:0] (.Din(accub_out), .Clk(accubClk), .AsyncReset(accubAsync), .En(|ACCUB_CLK), .Q(accub_int)); | |
wire out0Clk = clkInt[OUT0_CLK]; | |
wire out1Clk = clkInt[OUT1_CLK]; | |
wire out0Async = asyncInt[OUT0_ASYNC]; | |
wire out1Async = asyncInt[OUT1_ASYNC]; | |
wire [35:0] outRegIn0 = OutMode[1] ? DataOutCin0 : accua_int; | |
wire [35:0] outRegIn1 = OutMode[1] ? DataOutCin1 : accub_int; | |
wire [35:0] outRegOut0, outRegOut1; | |
alta_dff_en outReg0[35:0] (.Din(outRegIn0), .Clk(out0Clk), .AsyncReset(out0Async), .En(|OUT0_CLK), .Q(outRegOut0)); | |
alta_dff_en outReg1[35:0] (.Din(outRegIn1), .Clk(out1Clk), .AsyncReset(out1Async), .En(|OUT1_CLK), .Q(outRegOut1)); | |
assign DataOutCout0 = OutMode[1] ? outRegOut0 : accua_int; | |
assign DataOutCout1 = OutMode[1] ? outRegOut1 : accub_int; | |
assign {DataOut1, DataOut0} = OutMode[0] ? outRegOut1 : outRegOut0; | |
`endif | |
endmodule | |
module alta_i2c ( | |
input Clk, Rst, | |
input WrRdn, Strobe, | |
input Sdai, Scli, | |
input [7:0] DataIn, | |
input [7:0] Address, | |
output Wakeup, Irq, Ack, | |
output Sdao, Sclo, | |
output [7:0] DataOut | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter SLOT_ID = 4'b0000; | |
`ifdef ALTA_SIM | |
i2c_top inst ( | |
.i_sys_clk (Clk ), | |
.i_rst (Rst ), | |
.i_sys_stb (Strobe ), | |
.i_sys_rw (WrRdn ), | |
.im_sys_addr(Address), | |
.im_sys_data(DataIn ), | |
.i_scl (Scli ), | |
.i_sda (Sdai ), | |
.im_slot_id (SLOT_ID), | |
.om_sys_data(DataOut), | |
.o_sys_acko (Ack ), | |
.o_i2cirq (Irq ), | |
.o_i2cwkup (Wakeup ), | |
.o_sclo (Sclo ), | |
.o_sdao (Sdao ) | |
); | |
`endif | |
endmodule | |
module alta_spi ( | |
input Clk, Rst, | |
input WrRdn, Strobe, | |
input [7:0] DataIn, | |
input [7:0] Address, | |
input Mi, Si, Scki, Csi, | |
output Wakeup, Irq, Ack, | |
output So, Soe, Mo, Moe, Scko, Sckoe, | |
output [3:0] Cso, | |
output [3:0] Csoe, | |
output [7:0] DataOut | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter SLOT_ID = 4'b0000; | |
`ifdef ALTA_SIM | |
spi_top inst ( | |
.i_sys_clk (Clk ), | |
.i_rst (Rst ), | |
.i_sys_stb (Strobe ), | |
.i_sys_rw (WrRdn ), | |
.im_sys_addr(Address), | |
.im_sys_data(DataIn ), | |
.im_slot_id (SLOT_ID), | |
.i_spi_mi (Mi ), | |
.i_spi_si (Si ), | |
.i_spi_sck (Scki ), | |
.i_spi_cs (Csi ), | |
.om_sys_data(DataOut), | |
.o_sys_acko (Ack ), | |
.o_spiirq (Irq ), | |
.o_spiwkup (Wakeup ), | |
.o_spi_so (So ), | |
.o_spi_soe (Soe ), | |
.o_spi_mo (Mo ), | |
.o_spi_moe (Moe ), | |
.o_spi_scko (Scko ), | |
.o_spi_sckoe(Sckoe ), | |
.om_spi_cs (Cso ), | |
.om_spi_csoe(Csoe ) | |
); | |
`endif | |
endmodule | |
module alta_irda ( | |
input ir_clk, | |
input ir_reset, | |
input cal_en, | |
input pu_ivref, | |
input pu_pga, | |
input pu_dac, | |
input tia_reset, | |
input vip, | |
input vin, | |
output irx_data, | |
output cal_ready, | |
output [7:0] dac_cal_reg | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
endmodule | |
module alta_bram9k ( | |
input [17:0] DataInA, DataInB, | |
input [12:0] AddressA, AddressB, | |
input [ 1:0] ByteEnA, ByteEnB, | |
output [17:0] DataOutA, DataOutB, | |
input Clk0, ClkEn0, AsyncReset0, | |
input Clk1, ClkEn1, AsyncReset1, | |
input AddressStallA, WeA, ReA, | |
input AddressStallB, WeB, ReB | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter CLKMODE = 2'b0; // 00: independent mode, 01: input/output mode, 1x: read/write mode | |
parameter PORTA_CLKIN_EN = 1'b0; | |
parameter PORTA_CLKOUT_EN = 1'b0; | |
parameter PORTB_CLKIN_EN = 1'b0; | |
parameter PORTB_CLKOUT_EN = 1'b0; | |
parameter PORTA_RSTIN_EN = 1'b0; | |
parameter PORTA_RSTOUT_EN = 1'b0; | |
parameter PORTB_RSTIN_EN = 1'b0; | |
parameter PORTB_RSTOUT_EN = 1'b0; | |
parameter PORTA_OUTREG = 1'b0; | |
parameter PORTB_OUTREG = 1'b0; | |
parameter PORTA_WIDTH = 5'b0; | |
parameter PORTB_WIDTH = 5'b0; | |
parameter PACKEDMODE = 1'b0; | |
parameter INIT_VAL = 9216'b0; | |
parameter PORTA_WRITETHRU = 1'b0; | |
parameter PORTB_WRITETHRU = 1'b0; | |
parameter DLYTIME = 2'b00; | |
parameter RSEN_DLY = 2'b00; | |
`ifdef ALTA_SIM | |
reg [17:0] mem [511:0]; | |
reg [17:0] wrDataA, wrDataB, rdDataA, rdDataB; | |
integer i; | |
initial begin | |
for (i = 0; i < 512; i = i + 1) begin | |
mem[i] = INIT_VAL[i*18+17-:18]; | |
end | |
rdDataA = 18'b0; | |
rdDataB = 18'b0; | |
end | |
wire X36_MODE_A = PORTA_WIDTH[4]; | |
wire X36_MODE_B = PORTB_WIDTH[4]; | |
wire X36_MODE = X36_MODE_A | X36_MODE_B; | |
wire INOUT_MODE = X36_MODE | CLKMODE[0] | CLKMODE[1]; | |
wire RW_MODE = CLKMODE[1]; | |
wire clkInt0, clkInt1, rdAddrClkA, rdAddrClkB; | |
wire clkDataInA = PORTA_CLKIN_EN ? (INOUT_MODE ? clkInt0 : clkInt0) : (INOUT_MODE ? Clk0 : Clk0); | |
wire clkDataInB = PORTB_CLKIN_EN ? (INOUT_MODE ? clkInt0 : clkInt1) : (INOUT_MODE ? Clk0 : Clk1); | |
wire clkAddrInA = clkDataInA; | |
wire clkAddrInB = PORTB_CLKIN_EN ? (INOUT_MODE & !RW_MODE ? clkInt0 : clkInt1) : (INOUT_MODE & !RW_MODE ? Clk0 : Clk1); | |
wire clkOutA = PORTA_CLKOUT_EN ? (INOUT_MODE ? clkInt1 : clkInt0) : (INOUT_MODE ? Clk1 : Clk0); | |
wire clkOutB = PORTB_CLKOUT_EN ? (INOUT_MODE ? clkInt1 : clkInt1) : (INOUT_MODE ? Clk1 : Clk1); | |
wire rstInA = PORTA_RSTIN_EN ? (INOUT_MODE ? AsyncReset0 : AsyncReset0) : 1'b0; | |
wire rstInB = PORTB_RSTIN_EN ? (INOUT_MODE & !RW_MODE ? AsyncReset0 : AsyncReset1) : 1'b0; | |
wire rstOutA = PORTA_RSTOUT_EN ? (INOUT_MODE ? AsyncReset1 : AsyncReset0) : 1'b0; | |
wire rstOutB = PORTB_RSTOUT_EN ? (INOUT_MODE ? AsyncReset1 : AsyncReset1) : 1'b0; | |
alta_clkenctrl clkInt0_inst (.ClkIn(Clk0), .ClkEn(ClkEn0), .ClkOut(clkInt0)); | |
alta_clkenctrl clkInt1_inst (.ClkIn(Clk1), .ClkEn(ClkEn1), .ClkOut(clkInt1)); | |
alta_clkenctrl rdAddrClkA_inst(.ClkIn(clkAddrInA), .ClkEn(ReA), .ClkOut(rdAddrClkA)); | |
alta_clkenctrl rdAddrClkB_inst(.ClkIn(clkAddrInB), .ClkEn(ReB), .ClkOut(rdAddrClkB)); | |
wire [17:0] dataInRegA, dataInRegB; | |
wire [12:0] addrInRegA0, addrInRegB0; | |
wire [ 3:0] addrRdRegA, addrRdRegB; | |
wire [ 1:0] byteEnRegA, byteEnRegB; | |
wire weRegA, reRegA, weRegB, reRegB; | |
localparam BUF_DEL = 0; | |
wire [17:0] #BUF_DEL DataInA_buf = DataInA; | |
wire [17:0] #BUF_DEL DataInB_buf = DataInB; | |
wire [12:0] #BUF_DEL AddressA_buf = AddressA; | |
wire [12:0] #BUF_DEL AddressB_buf = AddressB; | |
wire [ 1:0] #BUF_DEL ByteEnA_buf = ByteEnA; | |
wire [ 1:0] #BUF_DEL ByteEnB_buf = ByteEnB; | |
wire #BUF_DEL WeA_buf = WeA; | |
wire #BUF_DEL ReA_buf = ReA; | |
wire #BUF_DEL WeB_buf = WeB; | |
wire #BUF_DEL ReB_buf = ReB; | |
alta_dff_stall dataInRegA_inst[17:0](.Din(DataInA_buf) , .Clk(clkDataInA), .AsyncReset(1'b0) , .Stall(1'b0) , .Q(dataInRegA)); | |
alta_dff_stall dataInRegB_inst[17:0](.Din(DataInB_buf) , .Clk(clkDataInB), .AsyncReset(1'b0) , .Stall(1'b0) , .Q(dataInRegB)); | |
alta_dff_stall addrInRegA_inst[12:0](.Din(AddressA_buf) , .Clk(clkAddrInA), .AsyncReset(rstInA), .Stall(AddressStallA), .Q(addrInRegA0)); | |
alta_dff_stall addrInRegB_inst[12:0](.Din(AddressB_buf) , .Clk(clkAddrInB), .AsyncReset(rstInB), .Stall(AddressStallB), .Q(addrInRegB0)); | |
alta_dff_stall addrRdRegA_inst[ 3:0](.Din(AddressA_buf[3:0]), .Clk(rdAddrClkA), .AsyncReset(rstInA), .Stall(AddressStallA), .Q(addrRdRegA)); | |
alta_dff_stall addrRdRegB_inst[ 3:0](.Din(AddressB_buf[3:0]), .Clk(rdAddrClkB), .AsyncReset(rstInB), .Stall(AddressStallB), .Q(addrRdRegB)); | |
alta_dff byteEnA_inst[ 1:0](.Din(ByteEnA_buf) , .Clk(clkDataInA), .AsyncReset(1'b0) , .Q(byteEnRegA)); | |
alta_dff byteEnB_inst[ 1:0](.Din(ByteEnB_buf) , .Clk(clkDataInB), .AsyncReset(1'b0) , .Q(byteEnRegB)); | |
alta_dff weRegA_inst (.Din(WeA_buf) , .Clk(clkDataInA), .AsyncReset(1'b0) , .Q(weRegA)); | |
alta_dff weRegB_inst (.Din(WeB_buf) , .Clk(clkDataInB), .AsyncReset(1'b0) , .Q(weRegB)); | |
alta_dff reRegA_inst (.Din(ReA_buf) , .Clk(clkAddrInA), .AsyncReset(1'b0) , .Q(reRegA)); | |
alta_dff reRegB_inst (.Din(ReB_buf) , .Clk(clkAddrInB), .AsyncReset(1'b0) , .Q(reRegB)); | |
// Generate read/write pulse | |
wire rdPulseA, rdPulseB, wrPulseA, wrPulseB; | |
alta_bram_pulse_generator #(.PULSE_DELAY(1)) genRdPulseA ( | |
.Clk(clkAddrInA), | |
.Ena(reRegA && !X36_MODE), | |
.Pulse(rdPulseA) | |
); | |
alta_bram_pulse_generator #(.PULSE_DELAY(2)) genWrPulseA ( | |
.Clk(clkAddrInA), | |
.Ena(weRegA), | |
.Pulse(wrPulseA) | |
); | |
alta_bram_pulse_generator #(.PULSE_DELAY(1)) genRdPulseB ( | |
.Clk(clkAddrInB), | |
.Ena(reRegB), | |
.Pulse(rdPulseB) | |
); | |
alta_bram_pulse_generator #(.PULSE_DELAY(2)) genWrPulseB ( | |
.Clk(clkAddrInB), | |
.Ena(weRegB && !X36_MODE), | |
.Pulse(wrPulseB) | |
); | |
wire [12:0] addrInRegA = PACKEDMODE ? {1'b0, addrInRegA0[11:0]} : addrInRegA0; | |
wire [12:0] addrInRegB = PACKEDMODE ? {1'b1, addrInRegB0[11:0]} : addrInRegB0; | |
wire [8:0] wrWlAddrA = X36_MODE_A ? {addrInRegA[12:5], 1'b0} : addrInRegA[12:4]; | |
wire [8:0] wrWlAddrB = X36_MODE_A ? {addrInRegA[12:5], 1'b1} : addrInRegB[12:4]; | |
wire [8:0] rdWlAddrA = X36_MODE_B ? {addrInRegB[12:5], 1'b0} : addrInRegA[12:4]; | |
wire [8:0] rdWlAddrB = X36_MODE_B ? {addrInRegB[12:5], 1'b1} : addrInRegB[12:4]; | |
wire [3:0] wrBlkAddrA = addrInRegA[3:0]; | |
wire [3:0] wrBlkAddrB = addrInRegB[3:0]; | |
wire [3:0] rdBlkAddrA = addrRdRegA[3:0]; | |
wire [3:0] rdBlkAddrB = addrRdRegB[3:0]; | |
`ifdef BRAM_BYTEEN_FIX // Needed for AG10K and AG15K | |
`define MASKA 18'h3ffff | |
`define MASKB 18'h3ffff | |
`else | |
`define MASKA maskA_x18 | |
`define MASKB maskB_x18 | |
`endif | |
wire [17:0] maskA_x18 = { {9{byteEnRegA[1]}}, {9{byteEnRegA[0]}} }; | |
wire [17:0] maskA_x9 = { {9{byteEnRegA[1] & wrBlkAddrA[3]}}, {9{byteEnRegA[0] & !wrBlkAddrA[3]}} }; | |
wire [17:0] maskA_x4 = (4'b1111 << wrBlkAddrA[3:2] * 4 + wrBlkAddrA[3]) & `MASKA; | |
wire [17:0] maskA_x2 = (2'b11 << wrBlkAddrA[3:1] * 2 + wrBlkAddrA[3]) & `MASKA; | |
wire [17:0] maskA_x1 = (1'b1 << wrBlkAddrA[3:0] * 1 + wrBlkAddrA[3]) & `MASKA; | |
wire [17:0] maskB_x18 = { {9{byteEnRegB[1]}}, {9{byteEnRegB[0]}} }; | |
wire [17:0] maskB_x9 = { {9{byteEnRegB[1] & wrBlkAddrB[3]}}, {9{byteEnRegB[0] & !wrBlkAddrB[3]}} }; | |
wire [17:0] maskB_x4 = (4'b1111 << wrBlkAddrB[3:2] * 4 + wrBlkAddrB[3]) & `MASKB; | |
wire [17:0] maskB_x2 = (2'b11 << wrBlkAddrB[3:1] * 2 + wrBlkAddrB[3]) & `MASKB; | |
wire [17:0] maskB_x1 = (1'b1 << wrBlkAddrB[3:0] * 1 + wrBlkAddrB[3]) & `MASKB; | |
wire [17:0] maskA = PORTA_WIDTH == 5'b00000 ? maskA_x18 : | |
PORTA_WIDTH == 5'b01000 ? maskA_x9 : | |
PORTA_WIDTH == 5'b01100 ? maskA_x4 : | |
PORTA_WIDTH == 5'b01110 ? maskA_x2 : | |
PORTA_WIDTH == 5'b01111 ? maskA_x1 : | |
PORTA_WIDTH == 5'b10000 ? maskA_x18 : 18'b0; | |
wire [17:0] maskB = PORTB_WIDTH == 5'b00000 ? maskB_x18 : | |
PORTB_WIDTH == 5'b01000 ? maskB_x9 : | |
PORTB_WIDTH == 5'b01100 ? maskB_x4 : | |
PORTB_WIDTH == 5'b01110 ? maskB_x2 : | |
PORTB_WIDTH == 5'b01111 ? maskB_x1 : | |
PORTB_WIDTH == 5'b10000 ? maskB_x18 : 18'b0; | |
wire [17:0] wrMaskA = X36_MODE_A ? maskA : maskA; | |
wire [17:0] wrMaskB = X36_MODE_A ? maskB_x18 : maskB; | |
wire [17:0] rdMaskA = X36_MODE ? 18'b0 : maskA; | |
wire [17:0] rdMaskB = X36_MODE ? 18'b0 : maskB; | |
wire noByteEnA = |PORTA_WIDTH[2:0]; | |
wire noByteEnB = |PORTB_WIDTH[2:0]; | |
always @ (posedge rdPulseA or posedge wrPulseA or posedge rdPulseB or posedge wrPulseB or posedge rstOutA or posedge rstOutB) begin | |
if (wrPulseA) begin | |
wrDataA = mem[wrWlAddrA]; | |
for (i = 0; i < 18; i = i + 1) begin | |
if (wrMaskA[i]) begin | |
wrDataA[i] = dataInRegA[i]; | |
end | |
end | |
mem[wrWlAddrA] = wrDataA; | |
end | |
if (wrPulseB || X36_MODE_A && wrPulseA) begin | |
wrDataB = mem[wrWlAddrB]; | |
for (i = 0; i < 18; i = i + 1) begin | |
if (wrMaskB[i]) begin | |
wrDataB[i] = dataInRegB[i]; | |
end | |
end | |
mem[wrWlAddrB] = wrDataB; | |
end | |
if (rstOutA) begin | |
rdDataA = 18'b0; | |
end else if (rdPulseA || X36_MODE_B && rdPulseB) begin | |
for (i = 0; i < 18; i = i + 1) begin | |
rdDataA[i] = !rstOutA && weRegA && PORTA_WRITETHRU && (noByteEnA | rdMaskA[i]) ? dataInRegA[i] : mem[rdWlAddrA][i]; | |
end | |
end | |
if (rstOutB) begin | |
rdDataB = 18'b0; | |
end else if (rdPulseB) begin | |
for (i = 0; i < 18; i = i + 1) begin | |
rdDataB[i] = !rstOutB && weRegB && PORTB_WRITETHRU && (noByteEnB | rdMaskB[i]) ? dataInRegB[i] : mem[rdWlAddrB][i]; | |
end | |
end | |
end | |
wire [4:0] rdPortWidthA = X36_MODE_B ? PORTB_WIDTH : PORTA_WIDTH; | |
wire [4:0] rdPortWidthB = PORTB_WIDTH; | |
wire [15:0] rdDataA_x16 = { rdDataA[16:9], rdDataA[7:0] }; | |
wire [8:0] rdDataA_x9 = rdBlkAddrA[3] ? rdDataA[17:9] : rdDataA[8:0]; | |
wire [3:0] rdDataA_x4 = rdDataA_x16 >> rdBlkAddrA[3:2]*4; | |
wire [1:0] rdDataA_x2 = rdDataA_x16 >> rdBlkAddrA[3:1]*2; | |
wire rdDataA_x1 = rdDataA_x16 >> rdBlkAddrA[3:0]; | |
wire [17:0] dataOutSelA = rdPortWidthA == 5'b00000 ? rdDataA : | |
rdPortWidthA == 5'b01000 ? { 1'b1, rdDataA_x9[7:0], 1'b1, rdDataA_x9[8], 7'h7f } : | |
rdPortWidthA == 5'b01100 ? { 11'h7FF , rdDataA_x4, 3'b111 } : | |
rdPortWidthA == 5'b01110 ? { 15'h7FFF , rdDataA_x2, 1'b1 } : | |
rdPortWidthA == 5'b01111 ? { 17'h1FFFF, rdDataA_x1 } : | |
rdPortWidthA == 5'b10000 ? rdDataA : 18'bx; | |
wire [15:0] rdDataB_x16 = { rdDataB[16:9], rdDataB[7:0] }; | |
wire [8:0] rdDataB_x9 = rdBlkAddrB[3] ? rdDataB[17:9] : rdDataB[8:0]; | |
wire [3:0] rdDataB_x4 = rdDataB_x16 >> rdBlkAddrB[3:2]*4; | |
wire [1:0] rdDataB_x2 = rdDataB_x16 >> rdBlkAddrB[3:1]*2; | |
wire rdDataB_x1 = rdDataB_x16 >> rdBlkAddrB[3:0]; | |
wire [17:0] dataOutSelB = rdPortWidthB == 5'b00000 ? rdDataB : | |
rdPortWidthB == 5'b01000 ? { 1'b1, rdDataB_x9[7:0], 1'b1, rdDataB_x9[8], 7'h7f } : | |
rdPortWidthB == 5'b01100 ? { 11'h7FF , rdDataB_x4, 3'b111 } : | |
rdPortWidthB == 5'b01110 ? { 15'h7FFF , rdDataB_x2, 1'b1 } : | |
rdPortWidthB == 5'b01111 ? { 17'h1FFFF, rdDataB_x1 } : | |
rdPortWidthB == 5'b10000 ? rdDataB : 18'bx; | |
wire [17:0] dataOutRegA, dataOutRegB; | |
alta_dff dataOutRegA_inst[17:0](.Din(dataOutSelA), .Clk(clkOutA), .AsyncReset(rstOutA), .Q(dataOutRegA)); | |
alta_dff dataOutRegB_inst[17:0](.Din(dataOutSelB), .Clk(clkOutB), .AsyncReset(rstOutB), .Q(dataOutRegB)); | |
assign DataOutA = PORTA_OUTREG ? dataOutRegA : dataOutSelA; | |
assign DataOutB = PORTB_OUTREG ? dataOutRegB : dataOutSelB; | |
`endif | |
endmodule | |
module alta_ram9k #(parameter DATA_WIDTH_A = 18, | |
ADDR_WIDTH_A = 9, | |
BYTE_WIDTH_A = 2, | |
DATA_WIDTH_B = 0, | |
ADDR_WIDTH_B = 0, | |
BYTE_WIDTH_B = 0, | |
INIT_VAL = 9216'b0, | |
CLKMODE = "read_write", | |
PACKEDMODE = "no", | |
PORTA_CLKIN_EN = "yes", | |
PORTA_CLKOUT_EN = "yes", | |
PORTB_CLKIN_EN = "yes", | |
PORTB_CLKOUT_EN = "yes", | |
PORTA_RSTIN_EN = "yes", | |
PORTA_RSTOUT_EN = "yes", | |
PORTB_RSTIN_EN = "yes", | |
PORTB_RSTOUT_EN = "yes", | |
PORTA_WRITEMODE = "normal", | |
PORTB_WRITEMODE = "normal", | |
PORTA_OUTREG = "no", | |
PORTB_OUTREG = "no", | |
INIT_PORT = "a") ( | |
input [DATA_WIDTH_A-1:0] DataInA, | |
input [DATA_WIDTH_B-1:0] DataInB, | |
output [DATA_WIDTH_A-1:0] DataOutA, | |
output [DATA_WIDTH_B-1:0] DataOutB, | |
input [ADDR_WIDTH_A-1:0] AddressA, | |
input [ADDR_WIDTH_B-1:0] AddressB, | |
input [BYTE_WIDTH_A-1:0] ByteEnA, | |
input [BYTE_WIDTH_B-1:0] ByteEnB, | |
input Clk0, ClkEn0, AsyncReset0, | |
input Clk1, ClkEn1, AsyncReset1, | |
input AddressStallA, WeA, ReA, | |
input AddressStallB, WeB, ReB | |
); | |
initial | |
begin | |
validate(DATA_WIDTH_A, ADDR_WIDTH_A, BYTE_WIDTH_A); | |
validate(DATA_WIDTH_B, ADDR_WIDTH_B, BYTE_WIDTH_B); | |
end | |
wire portClk0 = Clk0; | |
wire portClk1 = Clk1; | |
wire portClkEn0 = ClkEn0; | |
wire portClkEn1 = ClkEn1; | |
wire portAsyncReset0 = AsyncReset0; | |
wire portAsyncReset1 = AsyncReset1; | |
wire portWeA = WeA; | |
wire portWeB = WeB; | |
wire portReA = ReA; | |
wire portReB = ReB; | |
wire [17:0] portDataInA = portDataIn(DATA_WIDTH_A, DataInA, DATA_WIDTH_A, DataInA[(DATA_WIDTH_A+1)/2-1:0]); | |
wire [17:0] portDataInB = portDataIn(DATA_WIDTH_B, DataInB, DATA_WIDTH_A, DataInA[DATA_WIDTH_A-1:DATA_WIDTH_A/2]); | |
wire [12:0] portAddressA = portAddr(DATA_WIDTH_A, AddressA); | |
wire [12:0] portAddressB = portAddr(DATA_WIDTH_B, AddressB); | |
wire [ 1:0] portByteEnA = portByteEn(BYTE_WIDTH_A, ByteEnA, BYTE_WIDTH_A, 1'b0, ByteEnA); | |
wire [ 1:0] portByteEnB = portByteEn(BYTE_WIDTH_B, ByteEnB, BYTE_WIDTH_A, 1'b1, ByteEnA); | |
wire [17:0] portDataOutA, portDataOutB; | |
assign DataOutA = portDataOut(DATA_WIDTH_A, portDataOutA, portDataOutA); | |
assign DataOutB = portDataOut(DATA_WIDTH_B, portDataOutB, portDataOutA); | |
alta_bram9k ram_inst ( | |
.DataInA(portDataInA), .DataInB(portDataInB), | |
.AddressA(portAddressA), .AddressB(portAddressB), | |
.DataOutA(portDataOutA), .DataOutB(portDataOutB), | |
.Clk0(portClk0), .ClkEn0(portClkEn0), .AsyncReset0(portAsyncReset0), | |
.Clk1(portClk1), .ClkEn1(portClkEn1), .AsyncReset1(portAsyncReset1), | |
.ByteEnA(portByteEnA), .ByteEnB(portByteEnB), | |
.WeA(portWeA), .WeB(portWeB), | |
.ReA(portReA), .ReB(portReB), | |
.AddressStallA(AddressStallA), .AddressStallB(AddressStallB) | |
); | |
defparam ram_inst.PORTA_WIDTH = portCfg(DATA_WIDTH_A); | |
defparam ram_inst.PORTB_WIDTH = portCfg(DATA_WIDTH_B); | |
defparam ram_inst.CLKMODE = (CLKMODE == "independent" ? 2'b00 : (CLKMODE == "input_output" ? 2'b01 : (CLKMODE == "read_write" ? 2'b10: 2'bx))); | |
defparam ram_inst.PACKEDMODE = (PACKEDMODE == "no" ? 1'b0 : (PACKEDMODE == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_CLKIN_EN = (PORTA_CLKIN_EN == "no" ? 1'b0 : (PORTA_CLKIN_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_CLKOUT_EN = (PORTA_CLKOUT_EN == "no" ? 1'b0 : (PORTA_CLKOUT_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_CLKIN_EN = (PORTB_CLKIN_EN == "no" ? 1'b0 : (PORTB_CLKIN_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_CLKOUT_EN = (PORTB_CLKOUT_EN == "no" ? 1'b0 : (PORTB_CLKOUT_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_RSTIN_EN = (PORTA_RSTIN_EN == "no" ? 1'b0 : (PORTA_RSTIN_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_RSTOUT_EN = (PORTA_RSTOUT_EN == "no" ? 1'b0 : (PORTA_RSTOUT_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_RSTIN_EN = (PORTB_RSTIN_EN == "no" ? 1'b0 : (PORTB_RSTIN_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_RSTOUT_EN = (PORTB_RSTOUT_EN == "no" ? 1'b0 : (PORTB_RSTOUT_EN == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_OUTREG = (PORTA_OUTREG == "no" ? 1'b0 : (PORTA_OUTREG == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_OUTREG = (PORTB_OUTREG == "no" ? 1'b0 : (PORTB_OUTREG == "yes" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTA_WRITETHRU = (PORTA_WRITEMODE == "normal" || PORTA_WRITEMODE == "read_before_write" ? 1'b0 : (PORTA_WRITEMODE == "write_thru" ? 1'b1 : 1'bx)); | |
defparam ram_inst.PORTB_WRITETHRU = (PORTB_WRITEMODE == "normal" || PORTB_WRITEMODE == "read_before_write" ? 1'b0 : (PORTB_WRITEMODE == "write_thru" ? 1'b1 : 1'bx)); | |
defparam ram_inst.INIT_VAL = (INIT_PORT == "a" ? portInitVal(DATA_WIDTH_A, INIT_VAL) : INIT_PORT == "b" ? portInitVal(DATA_WIDTH_B, INIT_VAL) : 9216'b0); | |
task validate(input integer data_width, input integer addr_width, input integer byte_width); | |
reg error; | |
begin | |
error = 1'b0; | |
case (data_width) | |
36, 32: if (addr_width > 8 || byte_width != 4) error = 1'b1; | |
18, 16: if (addr_width > 9 || byte_width != 2) error = 1'b1; | |
9, 8: if (addr_width > 10 || byte_width != 1) error = 1'b1; | |
4: if (addr_width > 11 || byte_width != 0) error = 1'b1; | |
2: if (addr_width > 12 || byte_width != 0) error = 1'b1; | |
1: if (addr_width > 13 || byte_width != 0) error = 1'b1; | |
0: error = 1'b0; // port not used | |
default: $display("Memory %m has illegal data width %0d specified", data_width); | |
endcase | |
if (error) | |
$display("Memory %m has illegal data/address/byte enable width sepcified: %0d/%0d/%0d", data_width, addr_width, byte_width); | |
if (addr_width < 8) | |
$display("Memory %m has illegal address width %0d specified", addr_width); | |
end | |
endtask | |
function [4:0] portCfg(input integer data_width); | |
begin | |
case (data_width) | |
36, 32: portCfg = 5'b10000; | |
18, 16: portCfg = 5'b00000; | |
9, 8: portCfg = 5'b01000; | |
4: portCfg = 5'b01100; | |
2: portCfg = 5'b01110; | |
1: portCfg = 5'b01111; | |
0: portCfg = 5'b00000; | |
endcase | |
end | |
endfunction | |
function [9215:0] portInitVal(input integer data_width, input [9215:0] initVal); | |
begin : initval | |
integer i; | |
case (data_width) | |
36, 18, 9: | |
portInitVal = initVal; | |
32, 16, 8, 4, 2, 1: | |
for (i = 0; i < 512; i = i + 1) | |
portInitVal[i*18+17-:18] = { 1'b0, initVal[i*16+15-:8], 1'b0, initVal[i*16+7-:8] }; | |
0: | |
portInitVal = 9216'b0; | |
endcase | |
end | |
endfunction | |
function [17:0] portDataIn(input integer data_width, input [17:0] data, input integer data_width0, input [17:0] data0); | |
begin | |
case (data_width0) | |
36: portDataIn = data0[17:0]; | |
32: portDataIn = { 1'b1, data0[15:8], 1'b1, data0[7:0] }; | |
default: | |
case(data_width) | |
18: portDataIn = data[17:0]; | |
16: portDataIn = { 1'b1, data[15:8], 1'b1, data[7:0] }; | |
9: portDataIn = { 2{ data[8:0] } }; | |
8: portDataIn = { 2{ 1'b1, data[7:0] } }; | |
4: portDataIn = { 2{ 1'b1, { 2{ data[3:0] } } } }; | |
2: portDataIn = { 2{ 1'b1, { 4{ data[1:0] } } } }; | |
1: portDataIn = { 2{ 1'b1, { 8{ data[0:0] } } } }; | |
0: portDataIn = ~18'b0; | |
endcase | |
endcase | |
end | |
endfunction | |
function [12:0] portAddr(input integer data_width, input [13:0] addr); | |
begin | |
case (data_width) | |
1: portAddr = addr; | |
2: portAddr = { addr[11:0], 1'b1 }; | |
4: portAddr = { addr[10:0], 2'b11 }; | |
8,9: portAddr = { addr[ 9:0], 3'b111 }; | |
16,18: portAddr = { addr[ 8:0], 4'b1111 }; | |
32,36: portAddr = { addr[ 7:0], 5'b11111 }; | |
0: portAddr = ~13'b0; | |
endcase | |
end | |
endfunction | |
function [1:0] portByteEn(input integer byte_width, input [3:0] byteEn, input integer byte_width0, input integer portId, input [3:0] byteEn0); | |
begin | |
case (byte_width0) | |
4: portByteEn[1:0] = byteEn0[portId*2+1-:2]; | |
default: | |
case(byte_width) | |
2: portByteEn[1:0] = byteEn; | |
1: portByteEn[1:0] = { 2{ byteEn[0] } }; | |
endcase | |
endcase | |
end | |
endfunction | |
function [35:0] portDataOut(input integer data_width, input [17:0] data, input [17:0] data0); | |
begin | |
case (data_width) | |
36: portDataOut = { data, data0 }; | |
32: portDataOut = { data[16:9], data[7:0], data0[16:9], data0[7:0] }; | |
18: portDataOut = data; | |
16: portDataOut = { data[16:9], data[7:0] }; | |
9: portDataOut = { data[7], data[16:9] }; | |
8: portDataOut = data[16:9]; | |
4: portDataOut = data[ 6:3]; | |
2: portDataOut = data[ 2:1]; | |
1: portDataOut = data[ 0:0]; | |
0: portDataOut = 36'b0; | |
endcase | |
end | |
endfunction | |
endmodule | |
module alta_mcu ( | |
//inputs | |
//clock and reset | |
input CLK, | |
input JTCK, | |
input POR_n, | |
input EXT_CPU_RST_n, | |
input JTRST_n, | |
//uart | |
input UART_RXD, | |
input UART_CTS_n, | |
//jtag | |
input JTDI, | |
input JTMS, | |
//ram access | |
input EXT_RAM_EN, | |
input EXT_RAM_WR, | |
input [13:0] EXT_RAM_ADDR, //in word | |
input [3:0] EXT_RAM_BYTE_EN, | |
input [31:0] EXT_RAM_WDATA, | |
//ext ahb slave | |
input [1:0] HRESP_EXT, | |
input HREADY_OUT_EXT, | |
input [31:0] HRDATA_EXT, | |
output [1:0] HTRANS_EXT, | |
output [31:0] HADDR_EXT, | |
output HWRITE_EXT, | |
output HSEL_EXT, | |
output [31:0] HWDATA_EXT, | |
output [2:0] HSIZE_EXT, | |
output HREADY_IN_EXT, | |
//outputs | |
//flash | |
output FLASH_SCK, | |
output FLASH_CS_n, | |
//uart | |
output UART_TXD, | |
output UART_RTS_n, | |
//jtag | |
output JTDO, | |
//ram access | |
output [31:0] EXT_RAM_RDATA, | |
//inouts | |
//flash | |
output FLASH_IO0_SI, | |
output FLASH_IO1_SO, | |
output FLASH_IO2_WPn, | |
output FLASH_IO3_HOLDn, | |
input FLASH_IO0_SI_i, | |
input FLASH_IO1_SO_i, | |
input FLASH_IO2_WPn_i, | |
input FLASH_IO3_HOLDn_i, | |
output FLASH_SI_OE, | |
output FLASH_SO_OE, | |
output WPn_IO2_OE, | |
output HOLDn_IO3_OE, | |
//gpio | |
input [7:0] GPIO0_I, | |
input [7:0] GPIO1_I, | |
input [7:0] GPIO2_I, | |
output [7:0] GPIO0_O, | |
output [7:0] GPIO1_O, | |
output [7:0] GPIO2_O, | |
output [7:0] nGPEN0, | |
output [7:0] nGPEN1, | |
output [7:0] nGPEN2 | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter [23:0] FLASH_BIAS = 24'b0; | |
`ifdef ALTA_SIM | |
M3_SYS_TOP mcu_inst( | |
.CLK (CLK ), | |
.JTCK (JTCK ), | |
.POR_n (POR_n ), | |
.EXT_CPU_RST_n (EXT_CPU_RST_n ), | |
.JTRST_n (JTRST_n ), | |
.UART_RXD (UART_RXD ), | |
.UART_CTS_n (UART_CTS_n ), | |
.JTDI (JTDI ), | |
.JTMS (JTMS ), | |
.EXT_RAM_EN (EXT_RAM_EN ), | |
.EXT_RAM_WR (EXT_RAM_WR ), | |
.EXT_RAM_ADDR (EXT_RAM_ADDR ), | |
.EXT_RAM_BYTE_EN (EXT_RAM_BYTE_EN ), | |
.EXT_RAM_WDATA (EXT_RAM_WDATA ), | |
.FLASH_BIAS (FLASH_BIAS ), | |
.HRESP_EXT (HRESP_EXT ), | |
.HREADY_OUT_EXT (HREADY_OUT_EXT ), | |
.HRDATA_EXT (HRDATA_EXT ), | |
.HTRANS_EXT (HTRANS_EXT ), | |
.HADDR_EXT (HADDR_EXT ), | |
.HWRITE_EXT (HWRITE_EXT ), | |
.HSEL_EXT (HSEL_EXT ), | |
.HWDATA_EXT (HWDATA_EXT ), | |
.HSIZE_EXT (HSIZE_EXT ), | |
.HREADY_IN_EXT (HREADY_IN_EXT ), | |
.FLASH_SCK (FLASH_SCK ), | |
.FLASH_CS_n (FLASH_CS_n ), | |
.UART_TXD (UART_TXD ), | |
.UART_RTS_n (UART_RTS_n ), | |
.JTDO (JTDO ), | |
.EXT_RAM_RDATA (EXT_RAM_RDATA ), | |
.FLASH_IO0_SI (FLASH_IO0_SI ), | |
.FLASH_IO1_SO (FLASH_IO1_SO ), | |
.FLASH_IO2_WPn (FLASH_IO2_WPn ), | |
.FLASH_IO3_HOLDn (FLASH_IO3_HOLDn ), | |
.FLASH_IO0_SI_i (FLASH_IO0_SI_i ), | |
.FLASH_IO1_SO_i (FLASH_IO1_SO_i ), | |
.FLASH_IO2_WPn_i (FLASH_IO2_WPn_i ), | |
.FLASH_IO3_HOLDn_i(FLASH_IO3_HOLDn_i), | |
.FLASH_SI_OE (FLASH_SI_OE ), | |
.FLASH_SO_OE (FLASH_SO_OE ), | |
.WPn_IO2_OE (WPn_IO2_OE ), | |
.HOLDn_IO3_OE (HOLDn_IO3_OE ), | |
.GPIO0_I (GPIO0_I ), | |
.GPIO1_I (GPIO1_I ), | |
.GPIO2_I (GPIO2_I ), | |
.GPIO0_O (GPIO0_O ), | |
.GPIO1_O (GPIO1_O ), | |
.GPIO2_O (GPIO2_O ), | |
.nGPEN0 (nGPEN0 ), | |
.nGPEN1 (nGPEN1 ), | |
.nGPEN2 (nGPEN2 ) | |
); | |
`endif | |
endmodule | |
module alta_mcu_m3 ( | |
//inputs | |
//clock and reset | |
input CLK, | |
input JTCK, | |
input POR_n, | |
input EXT_CPU_RST_n, | |
input JTRST_n, | |
//uart | |
input UART_RXD, | |
input UART_CTS_n, | |
//jtag | |
input JTDI, | |
input JTMS, | |
//swd | |
output SWDO, | |
output SWDOEN, | |
//ram access | |
input EXT_RAM_EN, | |
input EXT_RAM_WR, | |
input [14:0] EXT_RAM_ADDR, //in word | |
input [3:0] EXT_RAM_BYTE_EN, | |
input [31:0] EXT_RAM_WDATA, | |
//ext ahb slave | |
input [1:0] HRESP_EXT, | |
input HREADY_OUT_EXT, | |
input [31:0] HRDATA_EXT, | |
output [1:0] HTRANS_EXT, | |
output [31:0] HADDR_EXT, | |
output HWRITE_EXT, | |
output HSEL_EXT, | |
output [31:0] HWDATA_EXT, | |
output [2:0] HSIZE_EXT, | |
output HREADY_IN_EXT, | |
//ext ahb master | |
output [1:0] HRESP_EXTM, | |
output HREADY_OUT_EXTM, | |
output [31:0] HRDATA_EXTM, | |
input [1:0] HTRANS_EXTM, | |
input [31:0] HADDR_EXTM, | |
input HWRITE_EXTM, | |
input HSEL_EXTM, | |
input [31:0] HWDATA_EXTM, | |
input [2:0] HSIZE_EXTM, | |
input HREADY_IN_EXTM, | |
input [2:0] HBURSTM, | |
input [3:0] HPROTM, | |
//outputs | |
//flash | |
output FLASH_SCK, | |
output FLASH_CS_n, | |
//uart | |
output UART_TXD, | |
output UART_RTS_n, | |
//jtag | |
output JTDO, | |
//ram access | |
output [31:0] EXT_RAM_RDATA, | |
//inouts | |
//flash | |
output FLASH_IO0_SI, | |
output FLASH_IO1_SO, | |
output FLASH_IO2_WPn, | |
output FLASH_IO3_HOLDn, | |
input FLASH_IO0_SI_i, | |
input FLASH_IO1_SO_i, | |
input FLASH_IO2_WPn_i, | |
input FLASH_IO3_HOLDn_i, | |
output FLASH_SI_OE, | |
output FLASH_SO_OE, | |
output WPn_IO2_OE, | |
output HOLDn_IO3_OE, | |
//gpio | |
input [7:0] GPIO0_I, | |
input [7:0] GPIO1_I, | |
input [7:0] GPIO2_I, | |
output [7:0] GPIO0_O, | |
output [7:0] GPIO1_O, | |
output [7:0] GPIO2_O, | |
output [7:0] nGPEN0, | |
output [7:0] nGPEN1, | |
output [7:0] nGPEN2 | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter [23:0] FLASH_BIAS = 24'b0; | |
parameter [7:0] CLK_FREQ = 8'b0; | |
parameter [0:0] BOOT_DELAY = 1'b0; | |
`ifdef ALTA_SIM | |
M3_SYS_TOP mcu_inst ( | |
.CLK (CLK ), | |
.JTCK (JTCK ), | |
.POR_n (POR_n ), | |
.EXT_CPU_RST_n (EXT_CPU_RST_n ), | |
.JTRST_n (JTRST_n ), | |
.UART_RXD (UART_RXD ), | |
.UART_CTS_n (UART_CTS_n ), | |
.JTDI (JTDI ), | |
.JTMS (JTMS ), | |
.SWDO (SWDO ), | |
.SWDOEN (SWDOEN ), | |
.EXT_RAM_EN (EXT_RAM_EN ), | |
.EXT_RAM_WR (EXT_RAM_WR ), | |
.EXT_RAM_ADDR (EXT_RAM_ADDR ), | |
.EXT_RAM_BYTE_EN (EXT_RAM_BYTE_EN ), | |
.EXT_RAM_WDATA (EXT_RAM_WDATA ), | |
.FLASH_BIAS (FLASH_BIAS ), | |
.CLK_FREQ (CLK_FREQ ), | |
.BOOT_DELAY (BOOT_DELAY ), | |
.HRESP_EXT (HRESP_EXT ), | |
.HREADY_OUT_EXT (HREADY_OUT_EXT ), | |
.HRDATA_EXT (HRDATA_EXT ), | |
.HTRANS_EXT (HTRANS_EXT ), | |
.HADDR_EXT (HADDR_EXT ), | |
.HWRITE_EXT (HWRITE_EXT ), | |
.HSEL_EXT (HSEL_EXT ), | |
.HWDATA_EXT (HWDATA_EXT ), | |
.HSIZE_EXT (HSIZE_EXT ), | |
.HREADY_IN_EXT (HREADY_IN_EXT ), | |
.HRESP_EXTM (HRESP_EXTM ), | |
.HREADY_OUT_EXTM (HREADY_OUT_EXTM ), | |
.HRDATA_EXTM (HRDATA_EXTM ), | |
.HTRANS_EXTM (HTRANS_EXTM ), | |
.HADDR_EXTM (HADDR_EXTM ), | |
.HWRITE_EXTM (HWRITE_EXTM ), | |
.HSEL_EXTM (HSEL_EXTM ), | |
.HWDATA_EXTM (HWDATA_EXTM ), | |
.HSIZE_EXTM (HSIZE_EXTM ), | |
.HREADY_IN_EXTM (HREADY_IN_EXTM ), | |
.HBURSTM (HBURSTM ), | |
.HPROTM (HPROTM ), | |
.FLASH_SCK (FLASH_SCK ), | |
.FLASH_CS_n (FLASH_CS_n ), | |
.UART_TXD (UART_TXD ), | |
.UART_RTS_n (UART_RTS_n ), | |
.JTDO (JTDO ), | |
.EXT_RAM_RDATA (EXT_RAM_RDATA ), | |
.FLASH_IO0_SI (FLASH_IO0_SI ), | |
.FLASH_IO1_SO (FLASH_IO1_SO ), | |
.FLASH_IO2_WPn (FLASH_IO2_WPn ), | |
.FLASH_IO3_HOLDn (FLASH_IO3_HOLDn ), | |
.FLASH_IO0_SI_i (FLASH_IO0_SI_i ), | |
.FLASH_IO1_SO_i (FLASH_IO1_SO_i ), | |
.FLASH_IO2_WPn_i (FLASH_IO2_WPn_i ), | |
.FLASH_IO3_HOLDn_i(FLASH_IO3_HOLDn_i), | |
.FLASH_SI_OE (FLASH_SI_OE ), | |
.FLASH_SO_OE (FLASH_SO_OE ), | |
.WPn_IO2_OE (WPn_IO2_OE ), | |
.HOLDn_IO3_OE (HOLDn_IO3_OE ), | |
.GPIO0_I (GPIO0_I ), | |
.GPIO1_I (GPIO1_I ), | |
.GPIO2_I (GPIO2_I ), | |
.GPIO0_O (GPIO0_O ), | |
.GPIO1_O (GPIO1_O ), | |
.GPIO2_O (GPIO2_O ), | |
.nGPEN0 (nGPEN0 ), | |
.nGPEN1 (nGPEN1 ), | |
.nGPEN2 (nGPEN2 ) | |
); | |
`endif | |
endmodule | |
module alta_remote ( | |
input clk, shift, update, din, reconfig, | |
output dout | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
`ifdef ALTA_SIM | |
`endif | |
endmodule | |
module alta_saradc ( | |
input adcenb, sclk, | |
input [3:0] insel, | |
input refsel, refin, divvi8, bgenb, | |
input [8:0] ain, | |
output eoc, | |
output [11:0] db | |
) /* synthesis syn_black_box */; | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
`ifdef ALTA_SIM | |
`endif | |
endmodule | |
module alta_gclksw ( | |
input resetn, ena, clkin0, clkin1, clkin2, clkin3, | |
input [1:0] select, | |
output clkout | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
parameter ENA_REG_MODE = 1'b0; | |
cycloneive_clkctrl #(.clock_type("global clock"), .ena_register_mode(ENA_REG_MODE ? "falling edge" : "none")) gclk_switch( | |
.ena(ena), | |
.inclk({clkin3, clkin2, clkin1, clkin0}), | |
.clkselect(select), | |
.outclk(clkout) | |
); | |
endmodule | |
module alta_rv32 ( | |
input sys_clk, | |
output mem_ahb_hready, | |
input mem_ahb_hreadyout, | |
output [1:0] mem_ahb_htrans, | |
output [2:0] mem_ahb_hsize, | |
output [2:0] mem_ahb_hburst, | |
output mem_ahb_hwrite, | |
output [31:0] mem_ahb_haddr, | |
output [31:0] mem_ahb_hwdata, | |
input mem_ahb_hresp, | |
input [31:0] mem_ahb_hrdata, | |
input slave_ahb_hsel, | |
input slave_ahb_hready, | |
output slave_ahb_hreadyout, | |
input [1:0] slave_ahb_htrans, | |
input [2:0] slave_ahb_hsize, | |
input [2:0] slave_ahb_hburst, | |
input slave_ahb_hwrite, | |
input [31:0] slave_ahb_haddr, | |
input [31:0] slave_ahb_hwdata, | |
output slave_ahb_hresp, | |
output [31:0] slave_ahb_hrdata, | |
input [7:0] gpio0_io_in, | |
output [7:0] gpio0_io_out_data, | |
output [7:0] gpio0_io_out_en, | |
input [7:0] gpio1_io_in, | |
output [7:0] gpio1_io_out_data, | |
output [7:0] gpio1_io_out_en, | |
output [1:0] sys_ctrl_clkSource, | |
output sys_ctrl_hseEnable, | |
output sys_ctrl_hseBypass, | |
output sys_ctrl_pllEnable, | |
input sys_ctrl_pllReady, | |
output sys_ctrl_sleep, | |
output sys_ctrl_stop, | |
output sys_ctrl_standby, | |
input [7:0] gpio2_io_in, | |
output [7:0] gpio2_io_out_data, | |
output [7:0] gpio2_io_out_en, | |
input [7:0] gpio3_io_in, | |
output [7:0] gpio3_io_out_data, | |
output [7:0] gpio3_io_out_en, | |
input [7:0] gpio4_io_in, | |
output [7:0] gpio4_io_out_data, | |
output [7:0] gpio4_io_out_en, | |
input [7:0] gpio5_io_in, | |
output [7:0] gpio5_io_out_data, | |
output [7:0] gpio5_io_out_en, | |
input [7:0] gpio6_io_in, | |
output [7:0] gpio6_io_out_data, | |
output [7:0] gpio6_io_out_en, | |
input [7:0] gpio7_io_in, | |
output [7:0] gpio7_io_out_data, | |
output [7:0] gpio7_io_out_en, | |
input [7:0] gpio8_io_in, | |
output [7:0] gpio8_io_out_data, | |
output [7:0] gpio8_io_out_en, | |
input [7:0] gpio9_io_in, | |
output [7:0] gpio9_io_out_data, | |
output [7:0] gpio9_io_out_en, | |
input ext_resetn, | |
output resetn_out, | |
output dmactive, | |
output swj_JTAGNSW, | |
output [3:0] swj_JTAGSTATE, | |
output [3:0] swj_JTAGIR, | |
input [7:0] ext_int, | |
input [3:0] ext_dma_DMACBREQ, | |
input [3:0] ext_dma_DMACLBREQ, | |
input [3:0] ext_dma_DMACSREQ, | |
input [3:0] ext_dma_DMACLSREQ, | |
output [3:0] ext_dma_DMACCLR, | |
output [3:0] ext_dma_DMACTC, | |
input [3:0] local_int, | |
input [1:0] test_mode, | |
input usb0_xcvr_clk, | |
input usb0_id | |
); | |
parameter coord_x = 0; | |
parameter coord_y = 0; | |
parameter coord_z = 0; | |
endmodule | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set_location_assignment PIN_13 -to clk | |
set_location_assignment PIN_48 -to led | |
set_location_assignment PIN_41 -to rst_n | |
set_location_assignment PIN_9 -to gpio[0] | |
set_location_assignment PIN_11 -to gpio[1] | |
set_location_assignment PIN_12 -to gpio[2] | |
set_location_assignment PIN_14 -to gpio[3] | |
set_location_assignment PIN_15 -to gpio[4] | |
set_location_assignment PIN_16 -to gpio[5] | |
set_location_assignment PIN_17 -to gpio[6] | |
set_location_assignment PIN_18 -to gpio[7] | |
set_location_assignment PIN_19 -to gpio[8] | |
set_location_assignment PIN_20 -to gpio[9] | |
set_location_assignment PIN_22 -to gpio[10] | |
set_location_assignment PIN_23 -to gpio[11] | |
set_location_assignment PIN_25 -to gpio[12] | |
set_location_assignment PIN_42 -to gpio[13] | |
set_location_assignment PIN_43 -to gpio[14] | |
set_location_assignment PIN_44 -to gpio[15] | |
set_location_assignment PIN_45 -to gpio[16] | |
set_location_assignment PIN_46 -to gpio[17] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module blink ( | |
input wire clk, | |
input wire rst_n, | |
output wire led, | |
output [17:0] gpio | |
); | |
wire clk_pll_o; | |
wire wireout; | |
reg [7:0] datain; | |
reg [7:0] dataout; | |
assign wireout = dataout[7:0]; | |
alta_spi spi_inst ( | |
.DataOut(wireout) | |
); | |
inpll pll_inst ( | |
.clkin(clk), // PLL.clkin MUST connect to PIN_XX_GB | |
.clkfb(clk_pll_o), | |
.pllen(1'b1), | |
.resetn(rst_n), | |
.clkout0en(1'b1), | |
.clkout1en(1'b0), | |
.clkout2en(1'b0), | |
.clkout3en(1'b0), | |
.clkout0(clk_pll_o), | |
.clkout1(), | |
.clkout2(), | |
.clkout3(), | |
.lock() | |
); | |
reg [24:0] counter; | |
assign led = counter[24]; | |
assign gpio[17:0] = counter[23:6]; | |
always @(posedge clk_pll_o or negedge rst_n) begin | |
if (!rst_n) | |
begin | |
counter <= 25'b0; | |
dataout <= 8'b1; | |
end | |
else | |
ounter <= counter + 1; | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment