verilog 串并转换电路
数字电路中的串并转换主要设计思想来源于用面积换速度,对数据流进行管理。实现串并转换的主要方式有双口RAM,FIFO,移位寄存器等,对于数据量较大的一般使用双口RAM或者FIFO实现,数据量较小的使用移位寄存器实现。
一、串转并
1位串行数据转8位并行数据
module serial2parallel(
input clk,
input rst_n,
input data_valid_i,
input data_in, //一位输入
output reg data_valid_o,
output reg [7:0] data_out //8位并行输出
);
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0)
data_out <= 8'b0;
//这里假设
else if (data_valid_i == 1'b1)begin
data_out <= {data_out[6:0], data_in}; //低位先赋值
//data_out <= {data_in,data_out[7:1]}; //高位先赋值
data_valid_o <= 1'b1;
end
else begin
data_valid_o <= 1'b0;
data_out <= data_out;
end
end
endmodule
仿真结果
//~ `New testbench
`timescale 1ns / 1ps
module tb_serial2parallel;
// serial2parallel Parameters
parameter PERIOD = 10;
// serial2parallel Inputs
reg clk = 0 ;
reg rst_n = 0 ;
reg data_valid_i = 0 ;
reg data_in = 0 ;
// serial2parallel Outputs
wire data_valid_o ;
wire [7:0] data_out ;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
initial
begin
#(PERIOD*2) rst_n = 1;
end
serial2parallel u_serial2parallel (
.clk ( clk ),
.rst_n ( rst_n ),
.data_valid_i ( data_valid_i ),
.data_in ( data_in ),
.data_valid_o ( data_valid_o ),
.data_out ( data_out [7:0] )
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_valid_i <= 0;
data_in <= 0;
end
else begin
data_valid_i <= 1;
data_in <= {$random} % 2;
end
end
endmodule
二、并转串
8位并行数据转1位串行数据
module parallel2serial(
input clk,
input rst_n,
input data_valid_i,
input [7:0]data_in,//输入的8位并行数据
output reg data_valid_o,
output reg data_out//输出的1位串行数据
);
reg[7:0]data;
reg [3:0]cnt;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)begin
data <= 8'b0;
data_out <= 1'b0;
data_valid_o <= 1'b0;
end
else if(data_valid_i && (cnt == 4'b0))begin
data <= data_in;
end
else if((4'b0001<= cnt)&&(cnt <= 4'b1000))begin
data <= data << 1;
data_out <= data[7];
data_valid_o <= 1'b1;
end
else begin
data <= 8'b0;
data_out <= 1'b0;
data_valid_o <= 1'b0;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 4'b0;
else if(data_valid_i)
cnt <= cnt + 1'b1;
else
cnt <= 1'b0;
end
endmodule
仿真结果
//~ `New testbench
`timescale 1ns / 1ps
module tb_parallel2serial;
// parallel2serial Parameters
parameter PERIOD = 10;
// parallel2serial Inputs
reg clk = 0 ;
reg rst_n = 0 ;
reg data_valid_i = 0 ;
reg [7:0] data_in = 0 ;
// parallel2serial Outputs
wire data_valid_o ;
wire data_out ;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
initial
begin
#(PERIOD*2) rst_n = 1;
end
parallel2serial u_parallel2serial (
.clk ( clk ),
.rst_n ( rst_n ),
.data_valid_i ( data_valid_i ),
.data_in ( data_in [7:0] ),
.data_valid_o ( data_valid_o ),
.data_out ( data_out )
);
initial
begin
#25 data_valid_i = 1;data_in = 8'b11011100;
#(PERIOD*8) data_valid_i = 0;data_in = 8'b00000000;
#20 data_valid_i = 1;data_in = 8'b11101001;
#(PERIOD*8) data_valid_i = 0;data_in = 8'b00000000;
#20 data_valid_i = 1;data_in = 8'b11110000;
#(PERIOD*8) data_valid_i = 0;data_in = 8'b00000000;
$finish;
end
endmodule
注意无论是串转并还是并转串,都要根据源数据实际的时序来修改代码逻辑。但是核心逻辑基本上是一样的,就是使用移位寄存器。