Commit 1563de24 authored by Andrey Filippov's avatar Andrey Filippov

converting eddr3 to the x393 project

parent b80c19f8
/*******************************************************************************
* Module: memctrl16
* Date:2015-01-10
* Author: andrey
* Description: 16-channel memory controller
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* memctrl16.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* memctrl16.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
`define use200Mhz 1
`define DEBUG_FIFO 1
module memctrl16 #(
parameter pri_width=16,
parameter PHASE_WIDTH = 8,
parameter SLEW_DQ = "SLOW",
parameter SLEW_DQS = "SLOW",
parameter SLEW_CMDA = "SLOW",
parameter SLEW_CLK = "SLOW",
parameter IBUF_LOW_PWR = "TRUE",
`ifdef use200Mhz
parameter real REFCLK_FREQUENCY = 200.0, // 300.0,
parameter HIGH_PERFORMANCE_MODE = "FALSE",
parameter CLKIN_PERIOD = 20, // 10, //ns >1.25, 600<Fvco<1200 // Hardware 150MHz , change to | 6.667
parameter CLKFBOUT_MULT = 16, // 8, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE | 16
parameter CLKFBOUT_MULT_REF = 16, // 18, // 9, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE | 6
parameter CLKFBOUT_DIV_REF = 4, // 200Mhz 3, // To get 300MHz for the reference clock
`else
parameter real REFCLK_FREQUENCY = 300.0,
parameter HIGH_PERFORMANCE_MODE = "FALSE",
parameter CLKIN_PERIOD = 10, //ns >1.25, 600<Fvco<1200
parameter CLKFBOUT_MULT = 8, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
parameter CLKFBOUT_MULT_REF = 9, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
parameter CLKFBOUT_DIV_REF = 3, // To get 300MHz for the reference clock
`endif
parameter DIVCLK_DIVIDE= 1,
parameter CLKFBOUT_PHASE = 0.000,
parameter SDCLK_PHASE = 0.000,
parameter CLK_PHASE = 0.000,
parameter CLK_DIV_PHASE = 0.000,
parameter MCLK_PHASE = 90.000,
parameter REF_JITTER1 = 0.010,
parameter SS_EN = "FALSE",
parameter SS_MODE = "CENTER_HIGH",
parameter SS_MOD_PERIOD = 10000,
parameter CMD_PAUSE_BITS= 10,
parameter CMD_DONE_BIT= 10,
parameter AXI_WR_ADDR_BITS = 13,
parameter AXI_RD_ADDR_BITS = 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
parameter CMD0_ADDR = 'h0800, // AXI write to command sequence memory
parameter CMD0_ADDR_MASK = 'h1800, // AXI read address mask for the command sequence memory
parameter PORT0_RD_ADDR = 'h0000, // AXI read address to generate busy
parameter PORT0_RD_ADDR_MASK = 'h1c00, // AXI read address mask to generate busy
parameter PORT1_WR_ADDR = 'h0400, // AXI read address to generate busy
parameter PORT1_WR_ADDR_MASK = 'h1c00, // AXI read address mask to generate busy
// parameters below to be ORed with CONTROL_ADDR and CONTROL_ADDR_MASK respectively
parameter DLY_LD_REL = 'h080, // address to generate delay load
parameter DLY_LD_REL_MASK = 'h380, // address mask to generate delay load
parameter DLY_SET_REL = 'h070, // address to generate delay set
parameter DLY_SET_REL_MASK = 'h3ff, // address mask to generate delay set
parameter RUN_CHN_REL = 'h000, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter RUN_CHN_REL_MASK = 'h3f0, // address mask to generate sequencer channel/run
parameter PATTERNS_REL = 'h020, // address to set DQM and DQS patterns (16'h0055)
parameter PATTERNS_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter PATTERNS_TRI_REL = 'h021, // address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter PATTERNS_TRI_REL_MASK = 'h3ff, // address mask to set DQM and DQS tristate patterns
parameter WBUF_DELAY_REL = 'h022, // extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter WBUF_DELAY_REL_MASK = 'h3ff, // address mask to set extra delay
parameter PAGES_REL = 'h023, // address to set buffer pages {port1_page[1:0],port1_int_page[1:0],port0_page[1:0],port0_int_page[1:0]}
parameter PAGES_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter CMDA_EN_REL = 'h024, // address to enable('h825)/disable('h824) command/address outputs
parameter CMDA_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter SDRST_ACT_REL = 'h026, // address to activate('h827)/deactivate('h826) active-low reset signal to DDR3 memory
parameter SDRST_ACT_REL_MASK = 'h3fe, // address mask for reset DDR3
parameter CKE_EN_REL = 'h028, // address to enable('h829)/disable('h828) CKE signal to memory
parameter CKE_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter DCI_RST_REL = 'h02a, // address to activate('h82b)/deactivate('h82a) Zynq DCI calibrate circuitry
parameter DCI_RST_REL_MASK = 'h3fe, // address mask for DCI calibrate circuitry
parameter DLY_RST_REL = 'h02c, // address to activate('h82d)/deactivate('h82c) delay calibration circuitry
parameter DLY_RST_REL_MASK = 'h3fe, // address mask for delay calibration circuitry
parameter EXTRA_REL = 'h02e, // address to set extra parameters (currently just inv_clk_div)
parameter EXTRA_REL_MASK = 'h3ff, // address mask for extra parameters
parameter REFRESH_EN_REL = 'h030, // address to enable('h31) and disable ('h30) DDR refresh
parameter REFRESH_EN_REL_MASK = 'h3fe, // address mask to enable/disable DDR refresh
parameter REFRESH_PER_REL = 'h032, // address to set refresh period in 32 x tCK
parameter REFRESH_PER_REL_MASK = 'h3ff, // address mask set refresh period
parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh
parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address
) (
input rst,
input clk,
input [15:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [15:0] need_rq,
output [15:0] channel_pgm_en, // channel can program sequence data
input [511:0] seq_data, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input [15:0] seq_wr, // strobe for writing sequencer data (address is autoincremented)
input [15:0] seq_done, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
// priority programming
// TODO: Move to ps7 instance in this module
input [3:0] pgm_addr, // channel address to program priority
input [width-1:0] pgm_data, // priority data for the channel
input pgm_en, // enable programming priority data (use different clock?)
// DDR3 interface
output SDRST, // DDR3 reset (active low)
output SDCLK, // DDR3 clock differential output, positive
output SDNCLK,// DDR3 clock differential output, negative
output [ADDRESS_NUMBER-1:0] SDA, // output address ports (14:0) for 4Gb device
output [2:0] SDBA, // output bank address ports
output SDWE, // output WE port
output SDRAS, // output RAS port
output SDCAS, // output CAS port
output SDCKE, // output Clock Enable port
output SDODT, // output ODT port
inout [15:0] SDD, // DQ I/O pads
output SDDML, // LDM I/O pad (actually only output)
inout DQSL, // LDQS I/O pad
inout NDQSL, // ~LDQS I/O pad
output SDDMU, // UDM I/O pad (actually only output)
inout DQSU, // UDQS I/O pad
inout NDQSU,
output DUMMY_TO_KEEP // to keep PS7 signals from "optimization"
// input MEMCLK
);
// TODO: copy from ddrc_test01.v
endmodule
/*******************************************************************************
* Module: scheduler16
* Date:2015-01-09
* Author: andrey
* Description: 16-channel programmable DDR memory access scheduler
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* scheduler16.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* scheduler16.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module scheduler16 #(
parameter width=16
)(
input rst,
input clk,
input [15:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [15:0] need_rq,
input en_sch, // needs to be disabled before next access can be scheduled
output need, // granted access is "needed" one, not just "wanted"
output grant, // single-cycle granted channel access
output [3:0] grant_chn, // granted channel number, valid with grant, stays valid until en_sch is deasserted
// todo: add programming sequencer address for software sequencer program? Or should it come from the channel?
input [3:0] pgm_addr, // channel address to program priority
input [width-1:0] pgm_data, // priority data for the channel
input pgm_en // enable programming priority data (use different clock?)
);
// reg [width-1:0] pri00,pri01,pri02,pri03,pri04,pri05,pri06,pri07,pri08,pri09,pri10,pri11,pri12,pri13,pri14,pri15;
reg [width*16-1:0] pri_reg;
reg [15:0] want_conf, need_conf,need_want_conf;
// wire new_want,new_need;
// wire event_w;
wire [15:0] want_set,need_set;
reg [15:0] want_set_r,need_set_r;
// reg event_r, want_r;
reg need_r;
reg [width*16-1:0] sched_state;
wire need_some=| need_rq;
// wire want_some=| want_rq;
wire [15:0] next_want_conf,next_need_conf;
wire [3:0] index; // channel index to select
wire index_valid; // selected index valid ("needed" or "wanted")
reg grant_r; // 1 cycle long
reg grant_sent; // turns on after grant, until en_sch is de-asserted
reg [3:0] grant_chn_r;
wire grant_w;
// assign event_w=new_want | new_need;
assign next_want_conf=(want_conf & want_rq) | want_set;
assign next_need_conf=(need_conf & need_rq) | need_set;
assign grant=grant_r;
assign grant_chn=grant_chn_r;
assign grant_w=en_sch && index_valid && !grant_sent;
generate
genvar i;
for (i=0;i<16;i=i+1) begin: pri_reg_block
always @ (posedge rst or posedge clk) begin
if (rst) pri_reg[width*i +: width] <= 0;
else if (pgm_en && (pgm_addr==i)) pri_reg[width*i +: width] <= pgm_data;
end
end
endgenerate
pri1hot16 i_pri1hot16_want(
.in(want_rq & ~want_conf ),
.out(want_set),
.some());
// .some(new_want));
pri1hot16 i_pri1hot16_need(
.in(need_rq & ~need_conf ),
.out(need_set),
.some());
// .some(new_need));
always @(posedge rst or posedge clk) begin
if (rst) begin
want_conf <= 0;
need_conf <= 0;
end else begin
want_conf <= next_want_conf;
need_conf <= next_need_conf;
need_want_conf<= need_some? next_need_conf: next_want_conf;
end
end
always @ (posedge clk) begin
want_set_r<=want_set;
need_set_r<=need_set;
//event_r <= event_w;
//want_r<= want_some;
need_r<= need_some;
end
// TODO: want remains, need is removed (both need and want should be deactivated on grant!)
// Block that sets initila process state and increments it on every change of the requests
generate
genvar i1;
for (i1=0;i1<16;i1=i1+1) begin: sched_state_block
always @ (posedge rst or posedge clk) begin
if (rst) pri_reg[width*i1 +: width] <= 0; // not needed?
else begin
if (want_set_r[i1] || need_set_r[i1]) sched_state[width*i1 +: width] <= pri_reg[width*i1 +: width];
// increment, but do not roll over
else if (&sched_state[width*i1 +: width] == 0) sched_state[width*i1 +: width]<=sched_state[width*i1 +: width]+1;
end
end
end
endgenerate
// Select the process to run
index_max_16 #(width) i_index_max_16(
.clk(clk),
.values(sched_state),
.mask(need_want_conf),
.need_in(need_r),
.index(index[3:0]),
.valid(index_valid),
.need_out(need));
always @(posedge rst or posedge clk) begin
if (rst) begin
grant_r <=0;
grant_sent <=0;
grant_chn_r <=0;
end else begin
grant_r <= grant_w; // en_sch && index_valid && !grant_sent;
grant_sent <= (grant_sent && en_sch) || grant_r;
if (grant_w) grant_chn_r <= index[3:0];
end
end
endmodule
/*******************************************************************************
* Module: index_max_16
* Date:2015-01-09
* Author: andrey
* Description: Find index of the maximal of 16 values (masked), 4 cycle latency
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* index_max_16.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* index_max_16.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module index_max_16 #(
parameter width=16
) (
input clk,
input [16*width-1:0] values,
input [15:0] mask,
input need_in, // at least one of the channels needs access
output [ 3:0] index,
output valid,
output need_out // need_in with matching delay
);
wire [width-1:0] max0001,max0203,max0405,max0607,max0809,max1011,max1213,max1415,max00010203,max04050607,max08091011, max12131415;
wire [width-1:0] max0001020304050607,max0809101112131415;
wire sel0001,sel0203,sel0405,sel0607,sel0809,sel1011,sel1213,sel1415,sel00010203,sel04050607;
wire sel08091011, sel12131415, sel0001020304050607,sel0809101112131415, sel;
reg sel0001_r,sel0203_r,sel0405_r,sel0607_r,sel0809_r,sel1011_r,sel1213_r,sel1415_r;
reg [1:0] sel00010203_r,sel04050607_r,sel08091011_r, sel12131415_r;
reg [2:0] sel0001020304050607_r,sel0809101112131415_r;
reg [3:0] valid_dly;
reg [3:0] need_dly;
// 1-st layer
masked_max_reg #(width) i_masked_max_reg0001(
.clk(clk),
.a(values[width*0 +: width]),
.mask_a(mask[0]),
.b(values[width*1 +: width]),
.mask_b(mask[1]),
.max(max0001),
.s(sel0001));
masked_max_reg #(width) i_masked_max_reg0203(
.clk(clk),
.a(values[width*2 +: width]),
.mask_a(mask[2]),
.b(values[width*3 +: width]),
.mask_b(mask[3]),
.max(max0203),
.s(sel0203));
masked_max_reg #(width) i_masked_max_reg0405(
.clk(clk),
.a(values[width*4 +: width]),
.mask_a(mask[4]),
.b(values[width*5 +: width]),
.mask_b(mask[5]),
.max(max0405),
.s(sel0405));
masked_max_reg #(width) i_masked_max_reg0607(
.clk(clk),
.a(values[width*6 +: width]),
.mask_a(mask[6]),
.b(values[width*7 +: width]),
.mask_b(mask[7]),
.max(max0607),
.s(sel0607));
masked_max_reg #(width) i_masked_max_reg0809(
.clk(clk),
.a(values[width*8 +: width]),
.mask_a(mask[8]),
.b(values[width*9 +: width]),
.mask_b(mask[9]),
.max(max0809),
.s(sel0809));
masked_max_reg #(width) i_masked_max_reg1011(
.clk(clk),
.a(values[width*10 +: width]),
.mask_a(mask[10]),
.b(values[width*11 +: width]),
.mask_b(mask[11]),
.max(max1011),
.s(sel1011));
masked_max_reg #(width) i_masked_max_reg1213(
.clk(clk),
.a(values[width*12 +: width]),
.mask_a(mask[12]),
.b(values[width*13 +: width]),
.mask_b(mask[13]),
.max(max1213),
.s(sel1213));
masked_max_reg #(width) i_masked_max_reg1415(
.clk(clk),
.a(values[width*14 +: width]),
.mask_a(mask[14]),
.b(values[width*15 +: width]),
.mask_b(mask[15]),
.max(max1415),
.s(sel1415));
// 2-nd layer
masked_max_reg #(width) i_masked_max_reg00010203(
.clk(clk),
.a(max0001),
.mask_a(&mask[1:0]),
.b(max0203),
.mask_b(&mask[3:2]),
.max(max00010203),
.s(sel00010203));
masked_max_reg #(width) i_masked_max_reg04050607(
.clk(clk),
.a(max0405),
.mask_a(&mask[5:4]),
.b(max0607),
.mask_b(&mask[7:6]),
.max(max04050607),
.s(sel04050607));
masked_max_reg #(width) i_masked_max_reg08091011(
.clk(clk),
.a(max0809),
.mask_a(&mask[9:8]),
.b(max1011),
.mask_b(&mask[11:10]),
.max(max08091011),
.s(sel08091011));
masked_max_reg #(width) i_masked_max_reg12131415(
.clk(clk),
.a(max1213),
.mask_a(&mask[13:12]),
.b(max1415),
.mask_b(&mask[15:14]),
.max(max12131415),
.s(sel12131415));
// 3-nd layer
masked_max_reg #(width) i_masked_max_reg0001020304050607(
.clk(clk),
.a(max00010203),
.mask_a(&mask[3:0]),
.b(max04050607),
.mask_b(&mask[7:4]),
.max(max0001020304050607),
.s(sel0001020304050607));
masked_max_reg #(width) i_masked_max_reg0809101112131415(
.clk(clk),
.a(max08091011),
.mask_a(&mask[11:8]),
.b(max12131415),
.mask_b(&mask[15:12]),
.max(max0809101112131415),
.s(sel0809101112131415));
// 4-th layer
masked_max_reg #(width) i_masked_max_reg(
.clk(clk),
.a(max0001020304050607),
.mask_a(&mask[7:0]),
.b(max0809101112131415),
.mask_b(&mask[15:8]),
.max(),
.s(sel));
always @ (posedge clk) begin
sel0001_r<=sel0001;
sel0203_r<=sel0203;
sel0405_r<=sel0405;
sel0607_r<=sel0607;
sel0809_r<=sel0809;
sel1011_r<=sel1011;
sel1213_r<=sel1213;
sel1415_r<=sel1415;
sel00010203_r[1:0]<={sel00010203,sel00010203?sel0203_r:sel0001_r};
sel04050607_r[1:0]<={sel04050607,sel04050607?sel0607_r:sel0405_r};
sel08091011_r[1:0]<={sel08091011,sel08091011?sel1011_r:sel0809_r};
sel12131415_r[1:0]<={sel12131415,sel12131415?sel1415_r:sel1213_r};
sel0001020304050607_r[2:0]<={sel0001020304050607,sel0001020304050607?sel04050607_r[1:0]:sel00010203_r[1:0]};
sel0809101112131415_r[2:0]<={sel0809101112131415,sel0809101112131415?sel12131415_r[1:0]:sel08091011_r[1:0]};
valid_dly[3:0] <= {valid_dly[2:0],|mask[15:0]};
need_dly[3:0] <= {need_dly[2:0],need_in};
end
assign index[3:0]={
sel,
sel?sel0809101112131415_r[2:0]:sel0001020304050607_r[2:0]};
assign valid=valid_dly[3];
assign need_out=need_dly[3];
endmodule
/*******************************************************************************
* Module: masked_max_reg
* Date:2015-01-09
* Author: andrey
* Description: Finds maximal of two masked values, registers result
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* masked_max_reg.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* masked_max_reg.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module masked_max_reg#(
parameter width=16
)(
input clk,
input [width-1:0] a,
input mask_a,
input [width-1:0] b,
input mask_b,
output [width-1:0] max,
output s
);
reg [width-1:0] max_r;
reg s_r;
assign s=s_r;
assign max=max_r;
wire s_w= mask_b && ((mask_a && (b>a)) || !mask_a);
always @ (posedge clk) begin
s_r <= s_w;
max_r <= (mask_a || mask_b)? (s_w?b:a): 0;
end
endmodule
/*******************************************************************************
* Module: pri1hot16
* Date:2015-01-09
* Author: andrey
* Description: Priority select one of 16 inputs
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* pri1hot16.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pri1hot16.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module pri1hot16(
input [15:0] in,
output [15:0] out,
output some
);
assign out={
in[15] & ~(|in[14:0]),
in[14] & ~(|in[13:0]),
in[13] & ~(|in[12:0]),
in[12] & ~(|in[11:0]),
in[11] & ~(|in[10:0]),
in[10] & ~(|in[ 9:0]),
in[ 9] & ~(|in[ 8:0]),
in[ 8] & ~(|in[ 7:0]),
in[ 7] & ~(|in[ 6:0]),
in[ 6] & ~(|in[ 5:0]),
in[ 5] & ~(|in[ 4:0]),
in[ 4] & ~(|in[ 3:0]),
in[ 3] & ~(|in[ 2:0]),
in[ 2] & ~(|in[ 1:0]),
in[ 1] & ~(|in[ 0:0]),
in[ 0]
};
assign some=|in;
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment