1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00
Konstantin Pavlov (pt) 40533743d7 Added altera cookbook
2015-12-15 22:44:58 +03:00

255 lines
7.8 KiB
Verilog

// Copyright 2007 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents,
// maskwork rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design
// License Agreement (either as signed by you or found at www.altera.com). By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed. By making this reference
// design file available, Altera expressly does not recommend, suggest or
// require that this reference design file be used in combination with any
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// Testbench
///////////////////////////////////////////
// Needs the altmult_add model in quartus/eda/sim_lib/altera_mf.v
// as well as the stratix II atom models.
module mult_shift_tb ();
reg fail;
reg clk,ena_in,ena_out,rst,a_signed,b_signed;
reg shift_not_mult,direction_right,shift_not_rot;
reg [31:0] data_a,data_b;
wire [63:0] data_o_w, data_o_x, data_o_y, data_o_z;
mult_shift_32_32 w (
.clk(clk),.ena_in(ena_in),.ena_out(ena_out),.rst(rst),
.a_signed(a_signed),.b_signed(b_signed),
.data_a(data_a),.data_b(data_b),
.data_o(data_o_w),
.shift_not_mult(shift_not_mult),
.direction_right(direction_right),
.shift_not_rot(shift_not_rot)
);
mult_32_32 x (.clk(clk),.ena_in(ena_in),.ena_out(ena_out),.rst(rst),
.a_signed(a_signed),.b_signed(b_signed),
.data_a(data_a),.data_b(data_b),
.data_o(data_o_x));
cpu_mult_cell y (.A_en(ena_out),
.E_ctrl_mul_cell_src1_signed(a_signed),
.E_ctrl_mul_cell_src2_signed(b_signed),
.E_src1_mul_cell(data_a),
.E_src2_mul_cell(data_b),
.M_en(ena_in),
.clk(clk),
.reset_n(!rst),
.A_mul_cell_result(data_o_y)
);
///////////////////////////////////////////
// functional model
///////////////////////////////////////////
reg mult_showing_r, mult_showing_rr;
wire signed [32:0] tmp_a;
wire signed [32:0] tmp_b;
wire signed [71:0] tmp_mult;
assign tmp_a = {a_signed & data_a[31],data_a};
assign tmp_b = {b_signed & data_b[31],data_b};
assign tmp_mult = tmp_a * tmp_b;
wire [31:0] tmp_shr = data_a >> data_b[4:0];
wire [31:0] tmp_shl = data_a << data_b[4:0];
wire [63:0] double_a = {data_a,data_a};
wire [63:0] signext_a = {{32{a_signed & data_a[31]}} ,data_a};
wire [31:0] tmp_ror = (double_a >> data_b[4:0]);
wire [31:0] tmp_rol = (double_a << data_b[4:0]) >> 32;
wire [31:0] tmp_asr = (signext_a >> data_b[4:0]);
wire [63:0] tmp_result = !shift_not_mult ? tmp_mult[63:0] :
{32'b0,
(shift_not_rot ? (direction_right ?
(a_signed ? tmp_asr : tmp_shr) : tmp_shl) :
(direction_right ? tmp_ror : tmp_rol)
)};
reg [63:0] wait_x,wait_y;
always @(posedge clk or posedge rst) begin
if (rst) begin
wait_x <= 0;
wait_y <= 0;
mult_showing_r <= 1'b0;
mult_showing_rr <= 1'b0;
end
else begin
if (ena_in) begin
wait_x <= tmp_result[63:0];
mult_showing_r <= !shift_not_mult;
end
if (ena_out) begin
wait_y <= wait_x;
mult_showing_rr <= mult_showing_r;
end
end
end
assign data_o_z = wait_y;
///////////////////////////////////////////
// test stim and verify
///////////////////////////////////////////
initial begin
clk = 1;
rst = 0;
ena_in = 1;
ena_out = 1;
fail = 0;
a_signed = 0;
b_signed = 0;
#10 rst = 1;
#10 rst = 0;
#5000000 if (!fail) $display ("PASS");
$stop();
end
always @(negedge clk) begin
ena_in = $random;
ena_out = $random;
shift_not_mult = $random;
direction_right = $random;
shift_not_rot = $random;
a_signed = $random;
b_signed = $random;
data_a = $random;
data_b = $random;
end
always begin
#500 clk = ~clk;
end
always @(negedge clk) begin
// compare pure multiplier against altmult version
#10 if (data_o_x !== data_o_y) begin
$display ("Simple MULT Mismatch at time %d",$time);
fail = 1;
end
// compare multshift unit against functional model
if (data_o_w !== data_o_z) begin
$display ("Shift MULT unit Mismatch at time %d",$time);
fail = 1;
end
// when in multiply mode compare between mult and multshift
// units
if (mult_showing_rr) begin
if (data_o_x !== data_o_z) begin
$display ("Mult showing - cross unit mismatch at time %d",$time);
fail = 1;
end
end
end
endmodule
///////////////////////////////////////////////////////
// altmult based multiplier used by NIOS, for
// testing purposes.
//
// The altmult_add model is in the quartus/eda/sim_lib/altera_mf.v
// library.
///////////////////////////////////////////////////////
module cpu_mult_cell (
// inputs:
A_en,
E_ctrl_mul_cell_src1_signed,
E_ctrl_mul_cell_src2_signed,
E_src1_mul_cell,
E_src2_mul_cell,
M_en,
clk,
reset_n,
// outputs:
A_mul_cell_result
)
;
output [ 63: 0] A_mul_cell_result;
input A_en;
input E_ctrl_mul_cell_src1_signed;
input E_ctrl_mul_cell_src2_signed;
input [ 31: 0] E_src1_mul_cell;
input [ 31: 0] E_src2_mul_cell;
input M_en;
input clk;
input reset_n;
wire [ 63: 0] A_mul_cell_result;
wire mul_clr;
assign mul_clr = ~reset_n;
altmult_add the_altmult_add
(
.aclr0 (mul_clr),
.aclr1 (mul_clr),
.clock0 (clk),
.clock1 (clk),
.dataa (E_src1_mul_cell),
.datab (E_src2_mul_cell),
.ena0 (M_en),
.ena1 (A_en),
.result (A_mul_cell_result),
.signa (E_ctrl_mul_cell_src1_signed),
.signb (E_ctrl_mul_cell_src2_signed)
);
defparam the_altmult_add.addnsub_multiplier_aclr1 = "UNUSED",
the_altmult_add.addnsub_multiplier_pipeline_aclr1 = "UNUSED",
the_altmult_add.addnsub_multiplier_register1 = "CLOCK0",
the_altmult_add.dedicated_multiplier_circuitry = "YES",
the_altmult_add.input_aclr_a0 = "ACLR0",
the_altmult_add.input_aclr_b0 = "ACLR0",
the_altmult_add.input_register_a0 = "CLOCK0",
the_altmult_add.input_register_b0 = "CLOCK0",
the_altmult_add.input_source_a0 = "DATAA",
the_altmult_add.input_source_b0 = "DATAB",
the_altmult_add.lpm_type = "altmult_add",
the_altmult_add.multiplier1_direction = "ADD",
the_altmult_add.multiplier_register0 = "UNREGISTERED",
the_altmult_add.number_of_multipliers = 1,
the_altmult_add.output_aclr = "ACLR1",
the_altmult_add.output_register = "CLOCK1",
the_altmult_add.signed_aclr_a = "ACLR0",
the_altmult_add.signed_aclr_b = "ACLR0",
the_altmult_add.signed_pipeline_register_a = "UNREGISTERED",
the_altmult_add.signed_pipeline_register_b = "UNREGISTERED",
the_altmult_add.signed_register_a = "CLOCK0",
the_altmult_add.signed_register_b = "CLOCK0",
the_altmult_add.width_a = 32,
the_altmult_add.width_b = 32,
the_altmult_add.width_result = 64;
endmodule