基於FPGA的素數累加和的計算

基於FPGA的素數累加和的計算

項目簡述

這個小項目其實是樂鑫筆試的一道題,感覺很有意思也有一定的難度,所以這裏我們實現這個功能,這裏注意一下實現功能只是相對於做題而言,並沒有進行算法上面的優化。

題目:素數又稱質數(在大於1的自然數中,除了1和此整數自身外,沒法被其他自然數整除)
a、用任意語言實現10000以內的所有素數之和
b、Verilog實現素數求和器。要求:輸入一個小於10000的任意數,輸出小於該數的所有素數之和。

本次實驗所用到的軟硬件環境如下:
1、VIVADO 2019.1
2、Modelsim 10.7
3、MATLAB 2015b

MATLAB代碼

因爲沒有理論知識,只是解題我們直接給出相應的代碼供大家學習:

clc;
clear all;

N = 10000;
sum = 2;

for i = 3:N
    flag = 1;
    for j = 2:i-1
        if(mod(i,j) == 0)
            flag = 0;
        end
    end
    if(flag == 1)
        sum = sum + i;
    end
end

當然這裏使用MATLAB有些違規,本來打算使用c語言,但是因爲c環境還需要重新安裝也就沒有使用。

Verilog代碼

我們直接給出b問題的代碼,代碼不再多說以爲內比較簡單,相信大家都可以看懂。
test模塊:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : https://blog.csdn.net/zhangningning1996
// Module Name  : test.v
// Create Time  : 2020-06-08 19:25:24
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************
module test(
    input                   sclk            ,
    input                   rst_n           ,
    input           [13:0]  data            ,
    input                   data_en         ,
    output  reg             ready           ,
    output  reg     [19:0]  sum_data        ,
    output  reg             sum_data_en     
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
reg                 [13:0]  data_r          ;
reg                 [13:0]  cnt_data        ;
reg                 [13:0]  cnt_cnt_data    ;
reg                         flag            ;
wire                [13:0]  mod             ;

 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
assign      mod             =              cnt_data%cnt_cnt_data; 


always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        data_r              <=              14'd0;
    else if(data_en == 1'b1)
        data_r              <=              data;
    else
        data_r              <=              data_r;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        ready               <=              1'b1;
    else if(data_en == 1'b1)
        ready               <=              1'b0;
    else if(sum_data_en == 1'b1)
        ready               <=              1'b1;
    else
        ready               <=              ready;
          
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt_data            <=              14'd2;
    else if(cnt_data == data_r && (flag == 1'b1 || cnt_cnt_data == cnt_data-1'b1))
        cnt_data            <=              14'd2;
    else if(ready == 1'b0 && mod == 0)
        cnt_data            <=              cnt_data + 1'b1; 
    else if(ready == 1'b0 && cnt_cnt_data == cnt_data-1'b1)
        cnt_data            <=              cnt_data + 1'b1;
    else
        cnt_data            <=              cnt_data;
        

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt_cnt_data        <=              14'd2;
    else if(cnt_cnt_data == cnt_data-1 || flag == 1'b1)
        cnt_cnt_data        <=              14'd2;
    else if(ready == 1'b0)
        cnt_cnt_data        <=              cnt_cnt_data + 1'b1;
    else
        cnt_cnt_data        <=              14'd2;
        
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        flag                <=              1'b0;
    else if(mod == 0)
        flag                <=              1'b1;
    else
        flag                <=              1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        sum_data            <=              20'd2;
    else if(data_en == 1'b1)
        sum_data            <=              20'd2;
    else if(cnt_cnt_data == cnt_data-1)
        sum_data            <=              sum_data + cnt_data;
    else
        sum_data            <=              sum_data;
        
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        sum_data_en         <=              1'b0;
    else if(cnt_data == data_r && (flag == 1'b1 || cnt_cnt_data == cnt_data-1'b1)) 
        sum_data_en         <=              1'b1;
    else
        sum_data_en         <=              1'b0; 

endmodule

爲了驗證我們實驗的正確性,我們進行了測試代碼的書寫
test_tb模塊:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : https://blog.csdn.net/zhangningning1996
// Module Name  : test_tb.v
// Create Time  : 2020-06-08 19:25:21
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module test_tb();
reg                     sclk                ;
reg                     rst_n               ;
reg                     data_en             ;
wire                    ready               ;
wire            [19:0]  sum_data            ;
wire                    sum_data_en         ;  

initial begin
    sclk            =           1'b0;
    rst_n           <=          1'b0;
    data_en         <=          1'b0;
    #(10000)
    rst_n           <=          1'b1;
    #(10000)
    data_en         <=          1'b1;
    #(10)
    data_en         <=          1'b0;
end

always # 5     sclk         =           ~sclk;
    

test test_inst(
    .sclk            (sclk              ),
    .rst_n           (rst_n             ),
    .data            (1000              ),
    .data_en         (data_en           ),
    .ready           (ready             ),
    .sum_data        (sum_data          ),
    .sum_data_en     (sum_data_en       )
);

endmodule

結果驗證

當輸入1000時,MATLAB運行的結果如下:
在這裏插入圖片描述
Modelsim仿真的結果如下:
在這裏插入圖片描述
經過上面的兩個圖形從而驗證了我們實驗的正確性。

總結

創作不易,認爲文章有幫助的同學們可以關注、點贊、轉發支持。爲行業貢獻及其微小的一部分。或者對文章有什麼看法或者需要更近一步交流的同學,可以加入下面的羣:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章