當前位置:
首頁 >
Verilog功能模块——串行数据转并行数据
發布時間:2025/3/13
47
豆豆
生活随笔
收集整理的這篇文章主要介紹了
Verilog功能模块——串行数据转并行数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一. 模塊功能與應用場景
模塊功能:接收串行數據,轉為并行數據。
應用場景:在SPI,Uart等串行協議接收側均有應用。
二. 模塊框圖與使用說明
有兩種模式(通過參數SDATA_IS_CONTINUOUS進行選擇):
1.數據連續模式,此時sdata_valid指示有效數據開始,在并行數據接收完成前,后面數據均有效。輸入時序如下圖。
2.數據不連續模式,此時sdata_valid指示當前數據有效。輸入時序如下圖。
注意:
1.sdata與sdata_valid應同步有效,且因為代碼中有同步處理,所以這兩者不需要與sclk的某邊沿同步
2.sdata應從最高位開始發
2.第一組數據和第二組數據之間的間隔可以為0~N個時鐘周期,即可以連續發不間隔,也可以有任意間隔。
三. 模塊代碼
/** @Author : Xu Dakang* @Email : XudaKang_up@qq.com* @Date : 2021-04-24 12:27:11* @LastEditors : Xu Dakang* @LastEditTime : 2021-04-25 21:08:14* @Filename : sdata2pdata.sv* @Description : 輸入串行數據,輸出并行數據,實現串轉并 */module sdata2pdata #(parameter PDATA_WIDTH = 24,parameter SDATA_IS_CONTINUOUS = 0 )(output logic [PDATA_WIDTH-1 : 0] pdata,output logic pdata_valid,input logic sdata,input logic sdata_valid,input logic sclk,input logic rstn );//< 輸入信號同步 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logic sdata_r1; logic sdata_r2; logic sdata_r3; always_ff @(posedge sclk) beginsdata_r1 <= sdata;sdata_r2 <= sdata_r1;sdata_r3 <= sdata_r2; endlogic sdata_valid_r1; logic sdata_valid_r2; always_ff @(posedge sclk) beginsdata_valid_r1 <= sdata_valid;sdata_valid_r2 <= sdata_valid_r1; end //< 輸入信號同步 ------------------------------------------------------------//> 串行數據計數 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logic [$clog2(PDATA_WIDTH+1)-1 : 0] sdata_cnt;logic sdata_cnt_en; always_ff @(posedge sclk, negedge rstn) beginif (~rstn)sdata_cnt_en <= '0;else if (SDATA_IS_CONTINUOUS)if (sdata_valid_r2 && (sdata_cnt == '0 || sdata_cnt == PDATA_WIDTH - 1 || sdata_cnt == PDATA_WIDTH))sdata_cnt_en <= 1'b1;else if (~sdata_valid_r2 && sdata_cnt == PDATA_WIDTH - 1)sdata_cnt_en <= 1'b0;elsesdata_cnt_en <= sdata_cnt_en;elsesdata_cnt_en <= sdata_valid_r2; endalways_ff @(posedge sclk, negedge rstn) beginif (~rstn)sdata_cnt <= '0;else if (sdata_cnt_en)if (sdata_cnt == PDATA_WIDTH) // 數據有效時,一組數據剛轉換完成,下一組的第一個數據來了,計為1sdata_cnt <= 'b1;else //! 數據有效時,一組數據還未轉換完成,計數加1sdata_cnt <= sdata_cnt + 1'b1;else if (sdata_cnt == PDATA_WIDTH) // 一組數據轉換完成,下一組數據沒馬上來,回到0sdata_cnt <= '0;elsesdata_cnt <= sdata_cnt; end //> 串行數據計數 ------------------------------------------------------------//< 生成輸出 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logic [PDATA_WIDTH-1 : 0] pdata_temp; // pdata的計算中間值 always_ff @(posedge sclk, negedge rstn) beginif (~rstn)pdata_temp <= '0;else if (sdata_cnt_en)pdata_temp <= {pdata_temp[PDATA_WIDTH-2 : 0], sdata_r3};elsepdata_temp <= pdata_temp; endalways_ff @(posedge sclk, negedge rstn) beginif (~rstn)pdata <= '0;else if (sdata_cnt == PDATA_WIDTH)pdata <= pdata_temp;elsepdata <= pdata; endalways_ff @(posedge sclk, negedge rstn) beginif (~rstn)pdata_valid <= '0;else if (sdata_cnt == PDATA_WIDTH)pdata_valid <= 1'b1;elsepdata_valid <= '0; end //< 生成輸出 ------------------------------------------------------------endmodule四. testbench
/** @Author : Xu Dakang* @Email : XudaKang_up@qq.com* @Date : 2021-04-24 12:27:28* @LastEditors : Xu Dakang* @LastEditTime : 2021-04-25 21:05:02* @Filename : sdata2pdata_tb.sv* @Description : testbench of sdata2pdata */module sdata2pdata_tb ();timeunit 1ns; timeprecision 10ps;localparam PDATA_WIDTH = 5; localparam SDATA_IS_CONTINUOUS = 1;logic [PDATA_WIDTH-1 : 0] pdata; logic pdata_valid;logic sdata; logic sdata_valid; logic sclk; logic rstn;// 實例化模塊 sdata2pdata #(.PDATA_WIDTH (PDATA_WIDTH),.SDATA_IS_CONTINUOUS (SDATA_IS_CONTINUOUS) ) sdata2pdata_inst(.*);// 產生測試數據 最大值 2^PDATA_WIDTH-1 localparam NUM = 15; logic [PDATA_WIDTH-1 : 0] pdata_list [NUM]; initial beginfor (int i = 0; i < NUM; i++) beginpdata_list[i] = {$random()} % (2**PDATA_WIDTH);end end// 生成時鐘 localparam CLKT = 2; initial beginsclk = 0;forever #(CLKT / 2) sclk = ~sclk; end// 數據連續模式 initial beginif (SDATA_IS_CONTINUOUS == 1) beginrstn = 0;sdata_valid = 0;#(CLKT * 2) rstn = 1;for (int i = 0; i < NUM; i++) beginsdata_valid = 1;for (int j = 0; j < PDATA_WIDTH; j++) beginsdata = pdata_list[i][PDATA_WIDTH-1-j];#(CLKT) sdata_valid = 0;end#(CLKT * ({$random} % 3)) ; // 數據連續模式時,可在各組數據間插入隨機時鐘間隔end#(CLKT * 10) $stop;end end// 數據不連續模式 initial beginif (SDATA_IS_CONTINUOUS == 0) beginrstn = 0;sdata_valid = 0;#(CLKT * 2) rstn = 1;for (int i = 0; i < NUM; i++) beginfor (int j = 0; j < PDATA_WIDTH; j++) beginsdata = pdata_list[i][PDATA_WIDTH-1-j];sdata_valid = 1;#CLKT ;sdata_valid = 0;#(CLKT * ({$random} % 3)) ; // 數據不連續模式時,可在同組數據間插入隨機時鐘間隔endsdata_valid = 0;#(CLKT * ({$random} % 3)) ;end#(CLKT * 10) $stop;end endendmodule五. 仿真驗證
仿真工具:Vivado 2020.2 Simulator。
數據連續模式,從結果可以看出,串轉并輸出正確。
數據不連續模式,同樣正確。
六. 工程分享
sdata2pdata 串轉并模塊 vivado 2020.2工程.7z
鏈接:https://pan.baidu.com/s/1wBCLjYqcjj0HGm_S9O5iOQ
提取碼:j3z4
總結
以上是生活随笔為你收集整理的Verilog功能模块——串行数据转并行数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义Matlab功能函数——10进制整
- 下一篇: ISE简介及其下载 安装 和谐 与 卸载