[Verilog]用Verilog实现串并转换/并串转换
2023-12-15 11:18:35
用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) begin
if(cnt == N/2 - 1) begin
cnt <= 14'b0;
clk_out <= ~clk_out;
end
else
cnt <= cnt + 1'b1;
end
always @(posedge clk or negedge rst_n) begin
if(~rst_n) data <= 4'h0;
else data <= {data[2:0], d};
end
always @(posedge clk_out or negedge rst_n) begin
if(~rst_n) para_data_out <= 4'h0;
else para_data_out <= data;
end
endmodule
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) begin
if (~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]}; //高位先赋值,右移
end
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
ser_bit_cnt <= {CNT_WIDTH{1'b0}};
valid <= 1'h0;
end
else if(ser_bit_cnt == DATA_WIDTH-1) begin
ser_bit_cnt <= {CNT_WIDTH{1'b0}};
valid = 1'b1;
end
else begin
ser_bit_cnt <= ser_bit_cnt + 1'b1;
valid <= 1'b0;
end
end
endmodule
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)begin
if(rst_n == 1'b0) begin
para_data_o <= {DATA_WITH{1'b0}};
cnt <= {CNT_WIDTH{1'd0}};
end
else begin
para_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)begin
if(rst_n == 1'b0) begin
para_data_o <= {DATA_WITH{1'b0}};
cnt <= {CNT_WIDTH{1'd0}};
end
else begin
para_data_o[cnt] <= data_i; //低位先赋值
cnt <= cnt + 1'b1;
end
end
*/
endmodule
文章来源:https://blog.csdn.net/gsjthxy/article/details/134928214
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!