【FPGA】Multifunctional ALU

Table of contents

Experimental requirements

source code

        top level module

        Data Entry Module

        ALU operation module

        result processing module

        Scan digital tube module

                Scan the top layer of the nixie tube

                Divider

                Nixie tube display

emulation code

Structure layer diagram

pin configuration


Experimental board: xc7a100tlc sg324-2L, 20 switches in total

Experimental requirements

Through the control of high and low bits, the input of 32-bit data A, B and operation mode is realized, the hexadecimal operation result of ALU is displayed through 8 digital tubes, and 4 operation signals ZF SF CF OF (judgment zero) are displayed through 4 LED lights , sign, carry, overflow judgment)

 

source code

        top level module

`timescale 1ns / 1ps

module TOP(
    input CLK_100M,
    input[15:0] in_data,
    input ctrl_in,
    input rst_,
    input CLK_A,
    input CLK_B,
    input CLK_OP,
    input ShowA,
    input ShowB,
    output[7:0] AN,
    output[7:0] SEG,
    output[3:0] out_flags
    );
    
    wire[31:0] a;
    wire[31:0] b;
    wire[31:0] res;
    wire[31:0] alu_f;
    wire[3:0] in_flags;
    reg[31:0] out_data;
    
    DataInput A(in_data, ctrl_in, CLK_A, rst_, a);
    DataInput B(in_data, ctrl_in, CLK_B, rst_, b);  //数据输入
    ALU alu(a, b, in_data[3:0], res, in_flags);
    ALU_F f(res, in_flags, CLK_OP, rst_, alu_f, out_flags);
    LED led(CLK_100M, rst_, out_data, AN, SEG);
    
    
    always@(ShowA or ShowB)
    begin
        if(!ShowA)
            out_data = a;
        else if(!ShowB)
            out_data = b;
        else
            out_data = alu_f;
    end
    
endmodule

        Data Entry Module

`timescale 1ns / 1ps

module DataInput(
    input[15:0] data_in,
    input ctrl_in,
    input clk,
    input rst_,
    output reg[31:0] data_out
    );
    
    always@(negedge clk or negedge rst_)
    begin
        if(!rst_)
            data_out <= 32'b0;
        else
        begin
            if(ctrl_in == 1'b0)
                data_out[15:0] <= data_in;
            else
                data_out[31:16] <= data_in;
        end
    end
    
endmodule

        ALU operation module

`timescale 1ns / 1ps

module ALU(
    input[31:0] a,
    input[31:0] b,
    input[31:0] op,
    output reg[32:0] res,
    output reg[3:0] flags
    );
    // flags: ZF    SF    CF   OF (高位->低位)
    //        判零  符号  进位  判溢
    
    always@(*)
    begin
        case(op)
            4'b0000:
            begin
                res <= a + b;
                flags[1] = res[32];
                flags[0] = a[31] ^ b[31] ^ res[31] ^ res[32];
            end
            4'b0001: res <= a << b;
            4'b0010: res <= ($signed(a) < $signed(b)) ? 1 : 0;
            4'b0011: res <= (a < b) ? 1 : 0;
            4'b0100: res <= a ^ b;
            4'b0101: res <= a >> b;
            4'b0110: res <= a | b;
            4'b0111: res <= a & b;
            4'b1000:
            begin
                res <= a - b;
                flags[1] = res[32];
                flags[0] = a[31] ^ b[31] ^ res[31] ^ res[32];
            end
            4'b1001: res <= $signed(a) >>> b;
        endcase
        flags[3] = (res == 32'd0) ? 1 : 0;
        flags[2] = res[31];
    end

endmodule

        result processing module

`timescale 1ns / 1ps

module ALU_F(
    input[32:0] res,
    input[3:0] in_flags,
    input clk,
    input rst_,
    output reg[32:0] alu_f,
    output reg[3:0] out_flags
    );
    
    always@(negedge clk or negedge rst_)
    begin
        if(!rst_)
            begin
                alu_f <= 32'b0;
                out_flags <= 4'b1000;
            end
        else if(clk)
            begin
                alu_f <= res;
                out_flags <= in_flags;
            end
    end
    
endmodule

        Scan digital tube module

                Scan the top layer of the nixie tube

                

`timescale 1ns / 1ps

module LED(
    input clk_100M,
    input rst_,
    input[31:0] data,
    output[7:0] AN,
    output[7:0] SEG
);
    wire clk_ref; //数码管刷新频率:500hz
    wire clk_inc; //数字刷新频率:10hz
     
    Fdiv fdiv(clk_100M,32'd100000,clk_ref);
    Scanner scanner(data,rst_,clk_ref,AN,SEG);
endmodule

                Divider

`timescale 1ns / 1ps

module Fdiv(
    input clk_in,
    input [31:0] count,
    output reg clk_out
    );
    reg[31:0] num;
    
    always@(posedge clk_in)
    begin
        if(num == count)
            begin
                clk_out <= ~clk_out;
                num <= 1'b0;
            end
        else
            num <= num + 1'b1;
    end
    
endmodule

                Nixie tube display

`timescale 1ns / 1ps

module Scanner(
    input[31:0] data,
    input rst_,
    input clk_ref,
    output reg[7:0] AN,
    output reg[7:0] SEG
    );
reg[3:0] data_x;
reg[2:0] bit;

always@(negedge rst_ or posedge clk_ref)
begin
    if(!rst_)
        bit <= 3'd0;
    else
        bit <= bit + 1'b1;
end

always@(*)
    begin
        case(bit)
            3'b000: begin AN <= 8'b1111_1110; data_x <= data[3:0]; end
            3'b001: begin AN <= 8'b1111_1101; data_x <= data[7:4]; end
            3'b010: begin AN <= 8'b1111_1011; data_x <= data[11:8]; end
            3'b011: begin AN <= 8'b1111_0111; data_x <= data[15:12]; end
            3'b100: begin AN <= 8'b1110_1111; data_x <= data[19:16]; end
            3'b101: begin AN <= 8'b1101_1111; data_x <= data[23:20]; end
            3'b110: begin AN <= 8'b1011_1111; data_x <= data[27:24]; end
            3'b111: begin AN <= 8'b0111_1111; data_x <= data[31:28]; end
         endcase
         
         case(data_x)
            4'b0000: SEG <= 8'b0000_0011;
            4'b0001: SEG <= 8'b1001_1111;
            4'b0010: SEG <= 8'b0010_0101;
            4'b0011: SEG <= 8'b0000_1101;  
            4'b0100: SEG <= 8'b1001_1001;
            4'b0101: SEG <= 8'b0100_1001;
            4'b0110: SEG <= 8'b0100_0001;
            4'b0111: SEG <= 8'b0001_1111;
            4'b1000: SEG <= 8'b0000_0001;
            4'b1001: SEG <= 8'b0000_1001;
            4'b1010: SEG <= 8'b0001_0001;
            4'b1011: SEG <= 8'b1100_0001;
            4'b1100: SEG <= 8'b0110_0011;
            4'b1101: SEG <= 8'b1000_0101;
            4'b1110: SEG <= 8'b0110_0001;
            4'b1111: SEG <= 8'b0111_0001;
        endcase
     end
endmodule

emulation code

`timescale 1ns / 1ps

module ALU_top_sim();
    reg[31:0] a;
    reg[31:0] b;
    reg[3:0] op;
    wire[32:0] res;
    wire[3:0] flags; //顺序:ZF、SF、CF、OF

initial
        begin
            a = 32'h8000_0003;
            b = 32'h0000_0001;
    
            #100
            op = 4'b0000;   //加法
           
            #100
            op = 4'b0001;   //逻辑左移
            
            #100
            op = 4'b0010;   //有符号数比较          

            #100
            op = 4'b0011;   //无符号数比较            

            #100
            op = 4'b0100;   //异或
            
            #100
            op = 4'b0101;   //逻辑右移
            
            #100
            op = 4'b0110;   //按位或
            
            #100
            op = 4'b0111;   //按位与
           
            #100
            op = 4'b1000;   //减法
            
            #100
            op = 4'b1001;   //算术右移
        end    
    ALU alu_sim(a,b,op,res,flags);

endmodule

Structure layer diagram

pin configuration

set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN E3} [get_ports CLK_100M]

set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN V5} [get_ports in_data[15]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN T4} [get_ports in_data[14]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN V6} [get_ports in_data[13]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN T5} [get_ports in_data[12]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN T6} [get_ports in_data[11]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN V7} [get_ports in_data[10]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN R8} [get_ports in_data[9]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U9} [get_ports in_data[8]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN T9} [get_ports in_data[7]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN V10} [get_ports in_data[6]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN R10} [get_ports in_data[5]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U11} [get_ports in_data[4]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN R11} [get_ports in_data[3]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U12} [get_ports in_data[2]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN T13} [get_ports in_data[1]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN V14} [get_ports in_data[0]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN T14} [get_ports ctrl_in]

set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets CLK_A]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets CLK_B]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets CLK_OP]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN N17} [get_ports rst_]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN P18} [get_ports CLK_A]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN P17} [get_ports CLK_B]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN R18} [get_ports CLK_OP]

set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets ShowA]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets ShowB]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U18} [get_ports ShowA]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U17} [get_ports ShowB]

set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U6} [get_ports out_flags[3]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN R5} [get_ports out_flags[2]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN U7} [get_ports out_flags[1]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN R6} [get_ports out_flags[0]]

set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN C9} [get_ports AN[7]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN C10} [get_ports AN[6]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN D10} [get_ports AN[5]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN C11} [get_ports AN[4]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN M17} [get_ports AN[3]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN J14} [get_ports AN[2]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN K13} [get_ports AN[1]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN P14} [get_ports AN[0]]

set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN F14} [get_ports SEG[7]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN N14} [get_ports SEG[6]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN J13} [get_ports SEG[5]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN G13} [get_ports SEG[4]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN F13} [get_ports SEG[3]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN G14} [get_ports SEG[2]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN M13} [get_ports SEG[1]]
set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN H14} [get_ports SEG[0]]

Guess you like

Origin blog.csdn.net/phoenixFlyzzz/article/details/130052504