用Verilog實現串并轉換/并串裝換
摘要
一、串并轉換模塊
? ? ? ?串轉并就是將低3位信號和輸入信號一起賦值。因為經過轉換后,碼元速率會將為原來四分之一,所以設置4分頻時鐘,將其輸出。而并轉串就是不斷右移,取高位輸出。
module serial2para(input clk, rst_n,input ser_data_in,output reg [3:0] para_data_out
);parameter N = 4;//四分頻模塊
reg [13:0] cnt;
reg clk_out;
reg [3:0] data;always @(posedge clk or negedge rst_n) beginif(cnt == N/2 - 1) begincnt <= 14'b0;clk_out <= ~clk_out;end elsecnt <= cnt + 1'b1;
endalways @(posedge clk or negedge rst_n) beginif(~rst_n) data <= 4'h0;else data <= {data[2:0], d};
endalways @(posedge clk_out or negedge rst_n) beginif(~rst_n) para_data_out <= 4'h0;else para_data_out <= data;
endendmodule
1.1 利用移位寄存器
? ? ? ? 串行轉并行數據輸出:采用位拼接技術(移位寄存器),將串行的數據總數先表示出來,然后發送一位數據加一,后面的接收的這樣標志:para_data_o <= {para_data_o[6:0], ser_data_i };
module serial_parallel #(parameter DATA_WIDTH = 8
)(input clk,input rst_n,input left_shift,input ser_data_in, //1位串行輸入output valid,output reg [DATA_WIDTH-1:0] para_data_o //8位并行輸出
);parameter CNT_WIDTH = $clog2(DATA_WIDTH);reg [CNT_WIDTH-1:0] ser_bit_cnt;always @(posedge clk or negedge rst_n) beginif (~rst_n)para_data_o <= {DATA_WIDTH{1'b0}};else if (left_shift == 1'b1)para_data_o <= {para_data_o[DATA_WIDTH-2:0], ser_data_in}; //低位先賦值,左移else if(left_shift == 1'b0)para_data_o <= {ser_data_in, para_data_o[DATA_WIDTH-1:1]}; //高位先賦值,右移
endalways @(posedge clk or negedge rst_n) beginif(~rst_n) beginser_bit_cnt <= {CNT_WIDTH{1'b0}};valid <= 1'h0;endelse if(ser_bit_cnt == DATA_WIDTH-1) beginser_bit_cnt <= {CNT_WIDTH{1'b0}};valid = 1'b1;endelse beginser_bit_cnt <= ser_bit_cnt + 1'b1;valid <= 1'b0;end
endendmodule
1.2 利用計數器
? ? ? ? 利用計數器cnt 時鐘計數,開始數據先給高位,每過一個時鐘周期,數據便給低一位。這樣便可以達到串轉并的效果。
module serial_parallel(parameter DATA_WITH = 8
)(input clk,input rst_n,input ser_data_in,input valid,output reg [DATA_WITH-1:0] para_data_o
);parameter CNT_WIDTH = $clog2(DATA_WITH);//msb first most significant bit 表示二進制數據的最高位
reg [DATA_WITH-1:0] cnt; //計數器0-7 always @(posedge clk or negedge rst_n)beginif(rst_n == 1'b0) beginpara_data_o <= {DATA_WITH{1'b0}};cnt <= {CNT_WIDTH{1'd0}};endelse beginpara_data_o[DATA_WITH-1 - cnt] <= ser_data_in; //高位先賦值cnt <= cnt + 1'b1;end
end/*
//lsb first (least significant bit) 表示二進制數據的最低位reg [2:0] cnt;always @(posedge clk or negedge rst_n)beginif(rst_n == 1'b0) beginpara_data_o <= {DATA_WITH{1'b0}};cnt <= {CNT_WIDTH{1'd0}};endelse beginpara_data_o[cnt] <= data_i; //低位先賦值cnt <= cnt + 1'b1;end
end
*/endmodule