Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.naic.edu/~phil/hardware/pdev/fpga/gx/sp/src/acc.v
Дата изменения: Thu Jun 26 04:27:55 2008
Дата индексирования: Sat Sep 6 19:49:04 2008
Кодировка:

// Jeff Mock
// 2030 Gough St.
// San Francisco, CA 94109
// jeff@mock.com
//
// Copyright 2005,2006
//
// $URL: https://www.mock.com/svn/pdev/trunk/gx/sp/src/acc.v $
// $Id: acc.v 913 2007-02-24 01:09:40Z jeff $


// Accumulators for signal integration
//

module acc (
ck,
reset,
creg_len,
creg_dshift_s0,
creg_dshift_s1,
creg_dshift_s2,
creg_dshift_s3,
sync_stokes,
frame_first,
frame_last,
frame_write,
frame_blank,
frame_cal,

x_s0,
x_s1,
x_s2,
x_s3,

y_s0,
y_s1,
y_s2,
y_s3,

sync_acc,
accdump,
x_acc_s0,
x_acc_s1,
x_acc_s2,
x_acc_s3,
y_acc_s0,
y_acc_s1,
y_acc_s2,
y_acc_s3,

acc_sat_s0s1,
acc_sat_s2s3,
acc_tot,
cal_tot
);

input ck;
input reset;
input [13:0] creg_len;
input [3:0] creg_dshift_s0;
input [3:0] creg_dshift_s1;
input [3:0] creg_dshift_s2;
input [3:0] creg_dshift_s3;
input sync_stokes;
input frame_first;
input frame_last;
input frame_write;
input frame_blank;
input frame_cal;

input [`N_MUL-1:0] x_s0;
input [`N_MUL-1:0] x_s1;
input [`N_MUL-1:0] x_s2;
input [`N_MUL-1:0] x_s3;

input [`N_MUL-1:0] y_s0;
input [`N_MUL-1:0] y_s1;
input [`N_MUL-1:0] y_s2;
input [`N_MUL-1:0] y_s3;

output sync_acc;
output accdump;
output [`N_ACC-1:0] x_acc_s0;
output [`N_ACC-1:0] x_acc_s1;
output [`N_ACC-1:0] x_acc_s2;
output [`N_ACC-1:0] x_acc_s3;
output [`N_ACC-1:0] y_acc_s0;
output [`N_ACC-1:0] y_acc_s1;
output [`N_ACC-1:0] y_acc_s2;
output [`N_ACC-1:0] y_acc_s3;

output acc_sat_s0s1;
output acc_sat_s2s3;
output [15:0] acc_tot;
output cal_tot;

// Munge transform length for stopping accumulator writes
//
wire [11:0] lend2;
reg [11:0] lend2m1;
assign lend2 = creg_len[12:1];
always @(posedge ck)
lend2m1 <= lend2 - 12'd1;

// Latch the frame control signals, these are generated on
// some other sync at the beginning of the datapath. They are
// each guaranteed to be asserted for an entire frame so it
// is safe to reclock them to out local sync.
//
reg frame_first_reg;
reg frame_last_reg;
reg frame_write_reg;
reg frame_blank_reg;
reg frame_cal_reg;
always @(posedge ck) begin
if (reset) begin
frame_first_reg <= 1'b0;
frame_last_reg <= 1'b0;
frame_write_reg <= 1'b0;
frame_blank_reg <= 1'b0;
frame_cal_reg <= 1'b0;
end else if (sync_stokes) begin
frame_first_reg <= frame_first;
frame_last_reg <= frame_last;
frame_write_reg <= frame_write;
frame_blank_reg <= frame_blank;
frame_cal_reg <= frame_cal;
end
end

// Generate blank signal for accumulators. Delay frame_blank_reg
// so that when the value comes out of d_shift is can be zeroed
// before getting accumulated.
reg blank_p1;
reg blank;
always @(posedge ck) begin
blank_p1 <= frame_blank_reg;
blank <= blank_p1;
end

// Count the numner of integrations actually performed. This
// count is produce quite early, 2-cycles after the beginning
// of a frame to accumulate and acc_tot value is latched until
// the next accumulation so that value is sure to be stable when
// the packet is dumped.
//
reg sync_stokes_d1;
reg sync_stokes_d2;
reg [15:0] acc_cnt;
reg [15:0] acc_tot;
reg cal_cnt;
reg cal_tot;
always @(posedge ck) begin
sync_stokes_d1 <= sync_stokes;
sync_stokes_d2 <= sync_stokes_d1;

if (reset)
acc_cnt <= 16'd0;
else if (sync_stokes_d1 & frame_write_reg) begin
if (frame_first_reg) begin
if (frame_blank_reg)
acc_cnt <= 16'd0;
else
acc_cnt <= 16'd1;
end else if (~frame_blank_reg)
acc_cnt <= acc_cnt + 16'd1;
end

if (reset)
acc_tot <= 16'd0;
else if (sync_stokes_d2 & frame_last_reg)
acc_tot <= acc_cnt;

// Keep track of cal signal. If it is set during the
// integration time, keep it set in cal_tot, this
// gets put in the output pack to know if cal was set
// at any point during the integration.
//
if (reset)
cal_cnt <= 1'b0;
else if (sync_stokes_d1)
if (frame_first_reg)
cal_cnt <= frame_cal_reg;
else
cal_cnt <= cal_cnt | frame_cal_reg;

if (reset)
cal_tot <= 1'b0;
else if (sync_stokes_d2 & frame_last_reg)
cal_tot <= cal_cnt;
end

// Generate mux select for accumulator. When asserted, the readback
// from memory is forced to zero so that the write to memory is
// a store rather than an accumulate. This is done during the first
// frame of an accumulation.
//
reg mem_store_p1;
reg mem_store;
always @(posedge ck) begin
mem_store_p1 <= frame_first_reg;
mem_store <= mem_store_p1;
end

// Generate write address for accumulator memory.
//
reg [11:0] waddr;
always @(posedge ck) begin
if (reset | sync_stokes)
waddr <= -(12'd5);
else
waddr <= waddr + 12'd1;
end

// Generate read address for accumulator memory.
//
reg [11:0] raddr;
always @(posedge ck) begin
if (reset || sync_stokes || raddr == lend2m1)
raddr <= 12'd0;
else
raddr <= raddr + 12'd1;
end

// Generate the sync output. The sync output is at twice
// the rate of the input sync since the raddr counter recycles
// every N/2 cycles. The accdump signal is asserted during the
// first N/2 cycles where the accumulator is being dump. The
// accumulators are dump at least twice and two more times
// for each creg_dcnt.
reg accdump_p;
reg accdump;
reg sync_acc;
wire raddr_1;
assign raddr_1 = (raddr == 12'd1);
always @(posedge ck) begin
sync_acc <= raddr_1;
if (reset) begin
accdump_p <= 1'b0;
accdump <= 1'b0;
end else begin
if (raddr_1) begin
accdump_p <= frame_last_reg;
accdump <= accdump_p & frame_last_reg;
end
end
end


// The write enable is a little tricky. A frame is N clock cycles,
// but we are only accumulating for N/2 clock cycles, no writes
// occur during the second N/2 cycles. This is offset 6-clocks for the
// the pipelining of accumulator datapath.
//
reg mem_wr;
reg [4:0] mem_wr_del;
always @(posedge ck) begin
mem_wr_del <= {mem_wr_del[3:0], sync_stokes};
if (reset)
mem_wr <= 1'b0;
else if (mem_wr_del[4] & frame_write_reg)
mem_wr <= 1'b1;
else if (waddr == lend2m1)
mem_wr <= 1'b0;
end

// The accumulators for s0 and s1 are unsigned
//
wire [`N_ACC-1:0] x_acc_s0;
wire x_sat_s0;
acc_us acc_xs0 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s0 ),
.raddr ( raddr ),
.waddr ( waddr ),
.mem_wr ( mem_wr ),
.blank ( blank ),
.mem_store ( mem_store ),
.s ( x_s0 ),
.acc ( x_acc_s0 ),
.acc_sat ( x_sat_s0 )
);

wire [`N_ACC-1:0] x_acc_s1;
wire x_sat_s1;
acc_us acc_xs1 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s1 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( x_s1 ),
.acc ( x_acc_s1 ),
.acc_sat ( x_sat_s1 )
);

wire [`N_ACC-1:0] y_acc_s0;
wire y_sat_s0;
acc_us acc_ys0 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s0 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( y_s0 ),
.acc ( y_acc_s0 ),
.acc_sat ( y_sat_s0 )
);

wire [`N_ACC-1:0] y_acc_s1;
wire y_sat_s1;
acc_us acc_ys1 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s1 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( y_s1 ),
.acc ( y_acc_s1 ),
.acc_sat ( y_sat_s1 )
);

reg acc_sat_s0s1;
always @(posedge ck)
acc_sat_s0s1 <= x_sat_s0 | x_sat_s1 | y_sat_s0 | y_sat_s1;

`ifdef N_FULL_STOKES
// The accumulators for s2 and s3 are signed
//
wire [`N_ACC-1:0] x_acc_s2;
wire x_sat_s2;
acc_s acc_xs2 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s2 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( x_s2 ),
.acc ( x_acc_s2 ),
.acc_sat ( x_sat_s2 )
);

wire [`N_ACC-1:0] x_acc_s3;
wire x_sat_s3;
acc_s acc_xs3 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s3 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( x_s3 ),
.acc ( x_acc_s3 ),
.acc_sat ( x_sat_s3 )
);

wire [`N_ACC-1:0] y_acc_s2;
wire y_sat_s2;
acc_s acc_ys2 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s2 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( y_s2 ),
.acc ( y_acc_s2 ),
.acc_sat ( y_sat_s2 )
);

wire [`N_ACC-1:0] y_acc_s3;
wire y_sat_s3;
acc_s acc_ys3 (
.ck ( ck ),
.reset ( reset ),
.creg_dshift ( creg_dshift_s3 ),
.raddr ( raddr ),
.waddr ( waddr ),
.blank ( blank ),
.mem_wr ( mem_wr ),
.mem_store ( mem_store ),
.s ( y_s3 ),
.acc ( y_acc_s3 ),
.acc_sat ( y_sat_s3 )
);

reg acc_sat_s2s3;
always @(posedge ck)
acc_sat_s2s3 <= x_sat_s2 | x_sat_s3 | y_sat_s2 | y_sat_s3;
`else
wire [`N_ACC-1:0] x_acc_s2;
wire [`N_ACC-1:0] x_acc_s3;
wire [`N_ACC-1:0] y_acc_s2;
wire y_sat_s3;
wire acc_sat_s2s3;

assign x_acc_s2 = `N_ACC'b0;
assign x_acc_s3 = `N_ACC'b0;
assign y_acc_s2 = `N_ACC'b0;
assign y_acc_s3 = `N_ACC'b0;
assign acc_sat_s2s3 = 1'b0;
`endif

endmodule