【牛客】8 企業真題

来源:https://www.cnblogs.com/magnolia666/archive/2023/03/11/17196617.html
-Advertisement-
Play Games

VL59 根據RTL圖編寫Verilog程式 這題比較簡單,照著寫就好了。 `timescale 1ns/1ns module RTL( input clk, input rst_n, input data_in, output reg data_out ); reg data_in_reg; al ...


VL59 根據RTL圖編寫Verilog程式

這題比較簡單,照著寫就好了。

`timescale 1ns/1ns

module RTL(
    input clk,
    input rst_n,
    input data_in,
    output reg data_out
    );
    reg data_in_reg;
    always@(posedge clk)
    begin
        if(~rst_n)
        begin
            data_in_reg <= 1'b0;
            data_out <= 1'b0;
        end
        else begin
            data_in_reg <= data_in;
            data_out <= data_in&~data_in_reg;
        end
    end

endmodule

VL60 使用握手信號實現跨時鐘域數據傳輸

題目只給了一個模塊的介面,實際看testbench要寫兩個模塊。

一開始用狀態機寫的,實在和答案對不上,還是照著題解寫了。單bit數據跨時鐘域常用方法:打兩拍。

`timescale 1ns/1ns
module data_driver(
    input clk_a,
    input rst_n,
    input data_ack,
    output reg [3:0]data,
    output reg data_req
    );
reg data_ack_reg_1;
reg data_ack_reg_2;
always @ (posedge clk_a or negedge rst_n)
begin
    if (!rst_n) begin
        data_ack_reg_1 <= 1'b0;
        data_ack_reg_2 <= 1'b0;
    end else begin
        data_ack_reg_1 <= data_ack;
        data_ack_reg_2 <= data_ack_reg_1;
    end
end
always@(posedge clk_a or negedge rst_n)
begin
    if(~rst_n)
        data <= 'd0;
    else if(~data_ack_reg_2&data_ack_reg_1)//每次傳輸結束數據+1
        data <= data + 1'b1;
end
reg [3:0]count;
always@(posedge clk_a or negedge rst_n)
begin
    if(~rst_n)
        count <= 'd0;
    else if(~data_req)
        count <= count + 1;
    else
        count <= 0;
end

always@(posedge clk_a or negedge rst_n)
begin
    if(~rst_n)
        data_req <= 'd0;
    else if(count == 4)
        data_req <= 1'b1;
    else if(~data_ack_reg_2&data_ack_reg_1)//傳輸結束,data_req清零
        data_req <= 1'b0;
end

endmodule

module data_receiver(
    input clk_b,
    input rst_n,
    input [3:0]data,
    input data_req,
    output reg data_ack
    );
reg data_req_reg_1;
reg data_req_reg_2;
always @ (posedge clk_b or negedge rst_n)
begin
    if (!rst_n) begin
        data_req_reg_1 <= 0;
        data_req_reg_2 <= 0;
    end else begin
        data_req_reg_1 <= data_req;
        data_req_reg_2 <= data_req_reg_1;
    end
end
always@(posedge clk_b or negedge rst_n)
begin
    if(~rst_n)
        data_ack <= 1'b0;
    else if(data_req_reg_2 == 1'b1)
        data_ack <= 1'b1;
    else
        data_ack <= 1'b0;
end
    
endmodule

VL61 自動售賣機

感覺用計數器會很簡單,狀態機複雜一點,不過題目要求用狀態機那就用吧。

 看了一下,感覺兩個狀態應該就夠了,一個狀態代表售賣機內沒錢,一個狀態代表售賣機內有5元錢。

`timescale 1ns/1ns

module sale(
   input                clk   ,
   input                rst_n ,
   input                sel   ,//sel=0,5$dranks,sel=1,10&=$drinks
   input          [1:0] din   ,//din=1,input 5$,din=2,input 10$
 
   output   reg  [1:0] drinks_out,//drinks_out=1,output 5$ drinks,drinks_out=2,output 10$ drinks
   output    reg        change_out   
);

reg state,next_state;
localparam S0=0,S1=1;
always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        state <= S0;
    else
        state <= next_state;
end    
always@(*)
begin
    case(state)
    S0:begin//0
        if(sel==0&&din==1||sel==1&&din==2)
            next_state = S0;
        else if(sel==1&&din==1)
            next_state = S1;
        else
            next_state = S0;
    end
    S1:begin//5
        next_state = din?S0:S1; 
    end
    endcase
end

always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)begin
        drinks_out <= 0;
        change_out <= 0;
    end else begin
        case(state)
        S0:begin
            if(sel==0&&din==1)begin
                drinks_out <= 1;
                change_out <= 0;
            end else if(sel==1&&din==2)begin
                drinks_out <= 2;
                change_out <= 0;
            end else if(sel==0&&din==2)begin
                drinks_out <= 1;
                change_out <= 1;
            end else begin
                drinks_out <= 0;
                change_out <= 0;
            end                
        end
        S1:begin
            if(sel==0&&din==1)begin
                drinks_out <= 1;
                change_out <= 1;
            end else if(sel==1&&din==2)begin
                drinks_out <= 2;
                change_out <= 1;
            end else if(sel==1&&din==1)begin
                drinks_out <= 2;
                change_out <= 0;
            end else begin
                drinks_out <= 0;
                change_out <= 0; 
            end             
        end
        endcase
    end
end
endmodule

 VL62 序列發生器

直接移位寄存器秒了,不過用狀態機的話所用寄存器會少一點。

`timescale 1ns/1ns

module sequence_generator(
    input clk,
    input rst_n,
    output reg data
    );
reg [5:0]data_reg;
always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)begin
        data_reg <= 6'b001011;
        data <= 1'b0;
    end else begin
        data_reg <= {data_reg[4:0],data_reg[5]};
        data <= data_reg[5];
    end
end
endmodule

 VL63 並串轉換

說是華為暑期實習的題,感覺題目出的一般,不懂是要考啥。

`timescale 1ns/1ns
module huawei5(
    input wire clk  ,
    input wire rst  ,
    input wire [3:0]d ,
    output wire valid_in ,
    output wire dout
    );

//*************code***********//
reg [3:0]data;
reg valid;
reg [1:0]count;
always@(posedge clk or negedge rst)
begin
    if(!rst)begin
        data <= 'd0;
        valid <= 1'b0;
        count <= 'd0;
    end else begin
        if(count == 'd3)begin
            valid <= 1'b1;
            count <= 0;
            data <= d;
        end else begin
            valid <= 1'b0;
            count <= count + 1;
            data <= data << 1;
        end
    end
end
assign dout = data[3];
assign valid_in = valid;
//*************code***********//

endmodule

VL64 時鐘切換

核心是沒有毛刺,我以為把sel打兩拍用來控制就行了,結果發現想簡單了。參考(數字 IC 設計)5.4 時鐘切換 - 知乎 (zhihu.com)

為了防止兩個輸出產生毛刺,兩個時鐘不能進行相反的極性轉換,由圖中clk0和clk1可以看出clk0的上升沿和clk1的下降沿是重合的。為避免毛刺的產生,需要在兩個時鐘都為低電平的時候進行時鐘切換。

反饋信號q1

`timescale 1ns/1ns

module huawei6(
    input wire clk0  ,
    input wire clk1  ,
    input wire rst  ,
    input wire sel ,
    output wire clk_out
);
//*************code***********//
reg q0, q1;
    
always@(negedge clk0 or negedge rst)
    if(!rst)
        q0 <= 0;
    else
        q0 <= ~sel & ~q1;
    
always@(negedge clk1 or negedge rst)
    if(!rst)
        q1 <= 0;
    else
        q1 <= sel & ~q0;

assign clk_out = (q0 & clk0) | (q1 & clk1);
//*************code***********//
endmodule

 VL65 狀態機與時鐘分頻

也可以用四個狀態,更簡單一點。

`timescale 1ns/1ns

module huawei7(
    input wire clk  ,
    input wire rst  ,
    output reg clk_out
);

//*************code***********//
reg[1:0]count;
reg state,next_state;
localparam S0=0,S1=1;
always@(posedge clk or negedge rst)
begin
    if(!rst)
        state <= S0;
    else
        state <= next_state;
end
always@(*)
begin
    case(state)
    S0:next_state=S1;
    S1:next_state=(count==2)?S0:S1;
    endcase
end
always@(posedge clk or negedge rst)
begin
    if(!rst)
        clk_out <= 1'b0;
    else begin
        if(state==S0)
            clk_out <= 1'b1;
        else
            clk_out <= 1'b0;
    end
end
always@(posedge clk or negedge rst)
begin
    if(!rst)
        clk_out <= 1'b0;
    else begin
        if(state==S1)
            count <= count + 1;
        else
            count <= 0;
    end
end
//*************code***********//
endmodule

VL66 超前進位加法器

 超前進位加法器原理:

 

 

 註意!進位C必須要拆開劃成最後那個表達式,不然Cn+1需要Cn的值的話,仍然會導致組合邏輯越來越長。劃成最後的表達式,Ci始終是三級組合邏輯:1、P、G的運算  2、多輸入與門  3、或門。

`timescale 1ns/1ns

module huawei8//四位超前進位加法器
(
    input wire [3:0]A,
    input wire [3:0]B,
    output wire [4:0]OUT
);

//*************code***********//
wire [3:0] G;
wire [3:0] P;
wire [3:0] F;
wire [4:1] C;
 Add1 u0
 (    .a(A[0]),
    .b(B[0]),
    .C_in(1'b0),
    .f(F[0]),
    .g(G[0]),
    .p(P[0])
 );
  Add1 u1
 (    .a(A[1]),
    .b(B[1]),
    .C_in(C[1]),
    .f(F[1]),
    .g(G[1]),
    .p(P[1])
 );
   Add1 u2
 (    .a(A[2]),
    .b(B[2]),
    .C_in(C[2]),
    .f(F[2]),
    .g(G[2]),
    .p(P[2])
 );
   Add1 u3
 (    .a(A[3]),
    .b(B[3]),
    .C_in(C[3]),
    .f(F[3]),
    .g(G[3]),
    .p(P[3])
 );
 CLA_4 u4
 (
    .P(P),
    .G(G),
    .C_in(C_in),
    .Ci(C),
    .Gm(),
    .Pm()
 );
  assign OUT={C[4],F};

//*************code***********//
endmodule



//////////////下麵是兩個子模塊////////

module Add1
(
        input a,
        input b,
        input C_in,
        output f,
        output g,
        output p
        );
assign f = a^b^C_in;//每一位的輸出
assign g = a&b;//生成信號
assign p = a|b;//傳播信號
endmodule


//CLA Carry Look Ahead
module CLA_4(
        input [3:0]P,
        input [3:0]G,
        input C_in,
        output [4:1]Ci,
        output Gm,
        output Pm
    );
assign Ci[1]=G[0]|P[0]&C_in;
assign Ci[2]=G[1]|P[1]&G[0]|P[1]&P[0]&C_in;
assign Ci[3]=G[2]|P[2]&G[1]|P[2]&P[1]&G[0]|P[2]&P[1]&P[0]&C_in;
assign Ci[4]=G[3]|P[3]&G[2]|P[3]&P[2]&G[1]|P[3]&P[2]&P[1]&G[0]|P[3]&P[2]&P[1]&P[0]&C_in;    //註意這裡一定要拆開寫,不然就和行波進位加法器差不多了。
//Gm和Pm是用來拓展更高位加法器的。
assign Gm=G[3]|P[3]&G[2]|P[3]&P[2]&G[1]|P[3]&P[2]&P[1]&G[0];
assign Pm=P[3]&P[2]&P[1]&P[0];
endmodule

VL67 十六進位計數器

這題放這裡多少有點離譜。。

`timescale 1ns/1ns

module counter_16(
   input                clk   ,
   input                rst_n ,
 
   output   reg  [3:0]  Q      
);
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        Q <= 4'b0;
    end else begin
        Q <= Q +1'b1;
    end
end
endmodule

VL68 同步FIFO

之前寫過,註意按題目給的介面,reg輸出wfull和rempty會晚一個周期。實際要麼在下一個讀/寫要空/滿的時候通過reg輸出,或者組合邏輯輸出。

`timescale 1ns/1ns

/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,
                       parameter WIDTH = 8)(
     input wclk
    ,input wenc
    ,input [$clog2(DEPTH)-1:0] waddr  
    ,input [WIDTH-1:0] wdata          
    ,input rclk
    ,input renc
    ,input [$clog2(DEPTH)-1:0] raddr  
    ,output reg [WIDTH-1:0] rdata         
);

reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];

always @(posedge wclk) begin
    if(wenc)
        RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
    if(renc)
        rdata <= RAM_MEM[raddr];
end 

endmodule  

/**********************************SFIFO************************************/
module sfifo#(
    parameter    WIDTH = 8,
    parameter     DEPTH = 16
)(
    input                     clk        , 
    input                     rst_n    ,
    input                     winc    ,
    input                      rinc    ,
    input         [WIDTH-1:0]    wdata    ,

    output reg                wfull    ,
    output reg                rempty    ,
    output wire [WIDTH-1:0]    rdata
);
parameter ADDR_WIDTH = $clog2(DEPTH);
reg [ADDR_WIDTH:0]waddr,raddr;//多一位用於比較空滿
always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        waddr <= 'd0;
    else if(winc&&~wfull)
        waddr <= waddr + 1;
end
always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        raddr <= 'd0;
    else if(rinc&&~rempty)
        raddr <= raddr + 1;
end
/*空滿判斷*/
always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)begin
        wfull <= 'd0;
        rempty <= 'd0;
    end else begin
        wfull <= (waddr[ADDR_WIDTH]==~raddr[ADDR_WIDTH])&&(waddr[ADDR_WIDTH-1:0]==raddr[ADDR_WIDTH-1:0]);
        rempty <= (raddr==waddr);
    end
end

dual_port_RAM #(.WIDTH(WIDTH),.DEPTH(DEPTH))
U0(
    .wclk(clk),
    .wenc(winc&&~wfull),
    .waddr(waddr[ADDR_WIDTH-1:0]),
    .wdata(wdata),
    .rclk(clk),
    .renc(rinc&&~rempty),
    .raddr(raddr[ADDR_WIDTH-1:0]),
    .rdata(rdata) );     
endmodule

 VL69 脈衝同步器(快到慢)

又是在前面做過的題。【牛客】6 跨時鐘域傳輸 - Magnolia666 - 博客園 (cnblogs.com)

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 要 在大數據,雲計算,人工智慧盛行的環境下,程式員該何去何從?企業自有的研發團隊又該如何規劃?這兩個問題在五年前,我就認真的思考和深入的分析過。程式開發模式基本經歷了以下階段。 傳統的程式開發階段 在對需求進行調研和分析後,最終得到系統的設計架構和技術選型;接下來就是程式員從第一行代碼純手工的編寫, ...
  • 這篇文章主要描述如何解決消息重發的問題,目前主流的消息隊列產品都採用了At least once的服務質量,這就導致了很難避免消息重發的情況,我們可以將消費者業務邏輯設計成冪等服務來解決消息重發問題。 ...
  • 【橋接設計模式詳解】Java/JS/Go/Python/TS不同語言實現 簡介 橋接模式(Bridge Pattern)是一種結構型設計模式,它將一個大類或一系列緊密相關的類拆分為抽象和實現兩個獨立的層次結構,來實現二者的解耦。參與橋接的介面是穩定的,用戶可以擴展和修改橋接中的類,但是不能改變介面。 ...
  • 在Python 中連接MSSQL,MySQL,SQLite,Redis,ElasticSearch,Mongodb,PostgreSQL,Oracle,RabbitMQ 等資料庫/中間件的方式 ...
  • 3、IOC創建對象的方法 使用無參構造創建對象,預設! 使用有參構造創建對象 下標賦值 <!--第一種 下標賦值--> <bean id="user" class="com.jan.pojo.User"> <constructor-arg index="0" value="鐘健"/> </bean> ...
  • 1、Celery的概念 Celery 是一個 基於python開發的分散式非同步消息任務隊列,通過它可以輕鬆的實現任務的非同步處理, 如果你的業務場景中需要用到非同步任務,就可以考慮使用celery, 舉幾個實例場景中可用的例子: 非同步任務:將耗時的操作任務提交給Celery去非同步執行,比如發送簡訊/郵件 ...
  • 一、基本語法元素 1.空白和註釋及語句 (1)空白: 換行符、回車符、空格鍵、水平定位鍵(Tab) 編譯器會忽略掉多餘的空白 作用:增加程式的易讀性 (2)註釋:主要作用是將代碼解釋其功能和作用,在編譯時,編譯器會直接將其丟棄,不會進入執行階段 1)// 在一行內的註釋,此種註釋是同一行內的註釋如果 ...
  • #####需求: 定義一個數組其中包含多個數字。用自己的方式最終實現,奇數放在數組的左邊,偶數放在數組的右邊。(可以創建其他數組,不必須在原數組中改變) 分析: 1.初始化一個數組,裡面既可以存儲奇數也可以存儲偶數(下麵稱這個個數組為原數組)。 2.再次定義兩個數組,一個用來存放從原數組中挑出來的奇 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...