OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 73 to Rev 74
    Reverse comparison

Rev 73 → Rev 74

/amber/trunk/hw/vlog/amber23/a23_barrel_shift_fpga.v
0,0 → 1,301
//////////////////////////////////////////////////////////////////
// //
// Barrel Shifter for Amber 2 Core //
// //
// The design is optimized for Altera family of FPGAs, //
// and it can be used directly or adapted other N-to-1 LUT //
// FPGA platforms. //
// //
// This file is part of the Amber project //
// http://www.opencores.org/project,amber //
// //
// Description //
// Provides 32-bit shifts LSL, LSR, ASR and ROR //
// //
// Author(s): //
// - Dmitry Tarnyagin, dmitry.tarnyagin@lockless.no //
// //
//////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2010-2013 Authors and OPENCORES.ORG //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// This source file is free software; you can redistribute it //
// and/or modify it under the terms of the GNU Lesser General //
// Public License as published by the Free Software Foundation; //
// either version 2.1 of the License, or (at your option) any //
// later version. //
// //
// This source 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 Lesser General Public License for more //
// details. //
// //
// You should have received a copy of the GNU Lesser General //
// Public License along with this source; if not, download it //
// from http://www.opencores.org/lgpl.shtml //
// //
//////////////////////////////////////////////////////////////////
 
 
module a23_barrel_shift_fpga (
 
input [31:0] i_in,
input i_carry_in,
input [7:0] i_shift_amount, // uses 8 LSBs of Rs, or a 5 bit immediate constant
input i_shift_imm_zero, // high when immediate shift value of zero selected
input [1:0] i_function,
 
output [31:0] o_out,
output o_carry_out
 
);
 
`include "a23_localparams.v"
 
wire [31:0] rot_prod; // Input rotated by the shift amount
 
wire [1:0] lsl_out; // LSL: {carry, bit_31}
wire [1:0] lsr_out; // LSR: {carry, bit_31}
wire [1:0] asr_out; // ASR: {carry, bit_31}
wire [1:0] ror_out; // ROR: {carry, bit_31}
 
reg [32:0] lsl_mask; // Left-hand mask
reg [32:0] lsr_mask; // Right-hand mask
reg [15:0] low_mask; // Mask calculation helper
 
reg [4:0] shift_amount; // Shift amount for the low-level shifter
 
reg [2:0] lsl_selector; // Left shift {shift_32, shift_over, shift_amount[4]}
reg [2:0] lsr_selector; // Right shift {shift_32, shift_over, shift_amount[4]}
reg [3:0] low_selector; // {shift_amount[3:0]}
 
reg shift_nzero; // Amount is not zero
reg shift_over; // Amount is 32 or higher
reg shift_32; // Amount is exactly 32
reg asr_sign; // Sign for ASR shift
reg direction; // Shift direction
 
wire [31:0] p_r; // 1 bit rotated rot_prod
wire [31:0] p_l; // Alias for the rot_prod
 
 
// Implementation details:
// Design is based on masking of rotated input by a left- and right- hand masks.
// Rotated product calculation requires 5 levels of combinational logic, and masks
// must be ready before the product is ready. In fact masks require just 3 to 4 levels
// of logic cells using 4-to-1/2x3-to-1 Altera.
 
always @*
begin
shift_32 = i_shift_amount == 32;
 
shift_over = |i_shift_amount[7:5];
 
shift_nzero = |i_shift_amount[7:0];
 
shift_amount = i_shift_amount[4:0];
 
if (i_shift_imm_zero) begin
if (i_function == LSR || i_function == ASR) begin
// The form of the shift field which might be
// expected to correspond to LSR #0 is used
// to encode LSR #32, which has a zero result
// with bit 31 of Rm as the carry output.
shift_nzero = 1'b1;
shift_over = 1'b1;
// Redundant and can be optimized out
// shift_32 = 1'b1;
end else if (i_function == ROR) begin
// RXR, (ROR w/ imm 0)
shift_amount[0] = 1'b1;
shift_nzero = 1'b1;
end
end
 
// LSB sub-selector calculation. Usually it is taken
// directly from the shift_amount, but ROR requires
// no masking at all.
case (i_function)
LSL: low_selector = shift_amount[3:0];
LSR: low_selector = shift_amount[3:0];
ASR: low_selector = shift_amount[3:0];
ROR: low_selector = 4'b0000;
endcase
 
// Left-hand MSB sub-selector calculation. Opaque for every function but LSL.
case (i_function)
LSL: lsl_selector = {shift_32, shift_over, shift_amount[4]};
LSR: lsl_selector = 3'b0_1_0; // Opaque mask selector
ASR: lsl_selector = 3'b0_1_0; // Opaque mask selector
ROR: lsl_selector = 3'b0_1_0; // Opaque mask selector
endcase
 
// Right-hand MSB sub-selector calculation. Opaque for LSL, transparent for ROR.
case (i_function)
LSL: lsr_selector = 3'b0_1_0; // Opaque mask selector
LSR: lsr_selector = {shift_32, shift_over, shift_amount[4]};
ASR: lsr_selector = {shift_32, shift_over, shift_amount[4]};
ROR: lsr_selector = 3'b0_0_0; // Transparent mask selector
endcase
 
// Direction
case (i_function)
LSL: direction = 1'b0; // Left shift
LSR: direction = 1'b1; // Right shift
ASR: direction = 1'b1; // Right shift
ROR: direction = 1'b1; // Right shift
endcase
 
// Sign for ASR shift
asr_sign = 1'b0;
if (i_function == ASR && i_in[31])
asr_sign = 1'b1;
end
 
// Generic rotate. Theoretical cost: 32x5 4-to-1 LUTs.
// Practically a bit higher due to high fanout of "direction".
generate
genvar i, j;
for (i = 0; i < 5; i = i + 1)
begin : netgen
wire [31:0] in;
reg [31:0] out;
for (j = 0; j < 32; j = j + 1)
begin : net
always @*
out[j] = in[j] & (~shift_amount[i] ^ direction) |
in[wrap(j, i)] & (shift_amount[i] ^ direction);
end
end
 
// Order is reverted with respect to volatile shift_amount[0]
assign netgen[4].in = i_in;
for (i = 1; i < 5; i = i + 1)
begin : router
assign netgen[i-1].in = netgen[i].out;
end
endgenerate
 
// Aliasing
assign rot_prod = netgen[0].out;
 
// Submask calculated from LSB sub-selector.
// Cost: 16 4-to-1 LUTs.
always @*
case (low_selector) // synthesis full_case parallel_case
4'b0000: low_mask = 16'hffff;
4'b0001: low_mask = 16'hfffe;
4'b0010: low_mask = 16'hfffc;
4'b0011: low_mask = 16'hfff8;
4'b0100: low_mask = 16'hfff0;
4'b0101: low_mask = 16'hffe0;
4'b0110: low_mask = 16'hffc0;
4'b0111: low_mask = 16'hff80;
4'b1000: low_mask = 16'hff00;
4'b1001: low_mask = 16'hfe00;
4'b1010: low_mask = 16'hfc00;
4'b1011: low_mask = 16'hf800;
4'b1100: low_mask = 16'hf000;
4'b1101: low_mask = 16'he000;
4'b1110: low_mask = 16'hc000;
4'b1111: low_mask = 16'h8000;
endcase
 
// Left-hand mask calculation.
// Cost: 33 4-to-1 LUTs.
always @*
casez (lsl_selector) // synthesis full_case parallel_case
7'b1??: lsl_mask = 33'h_1_0000_0000;
7'b01?: lsl_mask = 33'h_0_0000_0000;
7'b001: lsl_mask = { 1'h_1, low_mask, 16'h_0000};
7'b000: lsl_mask = {17'h_1_ffff, low_mask};
endcase
 
// Right-hand mask calculation.
// Cost: 33 4-to-1 LUTs.
always @*
casez (lsr_selector) // synthesis full_case parallel_case
7'b1??: lsr_mask = 33'h_1_0000_0000;
7'b01?: lsr_mask = 33'h_0_0000_0000;
7'b000: lsr_mask = { 1'h_1, bit_swap(low_mask), 16'h_ffff};
7'b001: lsr_mask = {17'h_1_0000, bit_swap(low_mask)};
endcase
 
// Alias: right-rotated
assign p_r = {rot_prod[30:0], rot_prod[31]};
 
// Alias: left-rotated
assign p_l = rot_prod[31:0];
 
// ROR MSB, handling special cases
assign ror_out[0] = i_shift_imm_zero ? i_carry_in :
p_r[31];
 
// ROR carry, handling special cases
assign ror_out[1] = i_shift_imm_zero ? i_in[0] :
shift_nzero ? p_r[31] :
i_carry_in;
 
// LSL MSB
assign lsl_out[0] = p_l[31] & lsl_mask[31];
 
// LSL carry, handling special cases
assign lsl_out[1] = shift_nzero ? p_l[0] & lsl_mask[32]:
i_carry_in;
 
// LSR MSB
assign lsr_out[0] = p_r[31] & lsr_mask[31];
 
// LSR carry, handling special cases
assign lsr_out[1] = i_shift_imm_zero ? i_in[31] :
shift_nzero ? p_r[31] & lsr_mask[32]:
i_carry_in;
 
// ASR MSB
assign asr_out[0] = i_in[31] ? i_in[31] :
p_r[31] & lsr_mask[31] ;
 
// LSR carry, handling special cases
assign asr_out[1] = shift_over ? i_in[31] :
shift_nzero ? p_r[31] :
i_carry_in;
 
// Carry and MSB are calculated as above
assign {o_carry_out, o_out[31]} = i_function == LSL ? lsl_out :
i_function == LSR ? lsr_out :
i_function == ASR ? asr_out :
ror_out ;
 
// And the rest of result is the masked rotated input.
assign o_out[30:0] = (p_l[30:0] & lsl_mask[30:0]) |
(p_r[30:0] & lsr_mask[30:0]) |
(~lsr_mask[30:0] & {31{asr_sign}});
 
// Rotate: calculate bit pos for level "level" and offset "pos"
function [4:0] wrap;
input integer pos;
input integer level;
integer out;
begin
out = pos - (1 << level);
wrap = out[4:0];
end
endfunction
 
// Swap bits in the input 16-bit value
function [15:0] bit_swap;
input [15:0] value;
integer i;
begin
for (i = 0; i < 16; i = i + 1)
bit_swap[i] = value[15 - i];
end
endfunction
 
endmodule
/amber/trunk/hw/vlog/amber23/a23_execute.v
466,7 → 466,11
// ========================================================
// Instantiate Barrel Shift
// ========================================================
`ifndef ALTERA_FPGA
a23_barrel_shift u_barrel_shift (
`else
a23_barrel_shift_fpga u_barrel_shift (
`endif
.i_in ( barrel_shift_in ),
.i_carry_in ( status_bits_flags[1] ),
.i_shift_amount ( shift_amount ),

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.