目录
在此,开始我的第一篇博客,一起加油,一起记录从零开始
1.串行信号转换为并行输出
比如要转换16位的信号,一个周期16位输出一次,前15个周期都在寄存,最后一个周期一块输出
module serial_to_parallel(
input clk,
input rst,
input din,
output reg [15:0] data //并行数据输出
)
reg[4:0] cnt; //记数转换个数
reg TEM_CS; //转换使能信号
always@(posedge clk or negedge rst)
begin
if(rst == 1'b0)//reset signial
begin
data <= 0;
cnt <= 0;
dout <= 0;
end
else if(TEM_CS == 1'b0)
begin
if (cnt == 5'd15)
begin //get all 16bit data,change dout
dout[15-cnt] <= din;
dout[15:1] <= data[15:1];
cnt <= 0;
end
else
begin
data[15-cnt] <= din;
cnt <= cnt + 1;
end
end
end
2.并行数据转换为串行输出
代码实现在conv_en的控制下,将16位并行数据,转换为串行数据输出,并行数据转换为串行数据后,第一个周期是空的,第二个周期才会有数据输出,因为复位过后的din_reg初始值为0。
module parallel_to_serial(
input clk,
input rst,
input conv_en,
input [15:0] din,
output reg dout,
);
parameter Num=16;
reg [15:0]din_reg;
reg [4:0]cnt;
//先输出高位,左移,若想输出低位则右移
always @(posedge clk or negedge rst)begin
if(!rst)
begin
dout <= 0;
din_reg<=3'd0;
cnt <= 0;
end
else if(conv_en == 1)
begin
if(cnt==Num - 1)
begin
dout<= din_reg[Num - 1];
din_reg<=din;
cnt<=1'd0;
end
else
begin
din_reg <= din_reg <<1;
dout<= din_reg[Num - 1];
cnt<=cnt+1'b1;
end
end
end
tb
`timescale 1ns/100ps
module tb_adf4351;
parameter SYSCLK_PERIOD = 100;// 10MHZ
reg SYSCLK;
reg NSYSRESET;
reg SYN_EN;
initial
begin
SYSCLK = 1'b1;
NSYSRESET = 1'b0;
SYN_EN = 1'b0;
end
//
// Reset Pulse
//
initial
begin
#(SYSCLK_PERIOD * 10 )
NSYSRESET = 1'b1;
end
//
// Clock Driver
//
always @(SYSCLK)
#(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;
reg [15:0] DIN;
integer j;
initial
begin
#(SYSCLK_PERIOD*150) SYN_EN = 1'b1;
#(SYSCLK_PERIOD*450) SYN_EN = 1'b0;
end
initial
begin
#1 DIN = 0;
for(j = 0;j<20;j = j+1)
begin
#(SYSCLK_PERIOD*100) DIN = 16'hccee;
#(SYSCLK_PERIOD*100) DIN = 16'haaaa;
#(SYSCLK_PERIOD*100) DIN = 16'hccee;
#(SYSCLK_PERIOD*100) DIN = 16'haaaa;
#(SYSCLK_PERIOD*100) DIN = 16'hccee;
end
end
wire dout;
wire [15:0]din_reg;
wire [4:0]cnt;
ADF4351_CTRL ADF4351_CTRL_0 (
// Inputs
.clk(SYSCLK),
.rst(NSYSRESET),
.din(DIN),
// Outputs
.dout(dout ),
.din_reg(din_reg),
.cnt(cnt),
.SYN_CLK_F( SYN_CLK_F)
);
endmodule
3.移位寄存器
//延时N个clk时钟周期
parameter N = 10;
reg [N-1:0] temp;
reg input; //需要打拍的信号
reg input_dly10; //打拍后的信号
always@(posedge clk or negedge rst)
if(!rst)
temp <= 0;
else
temp <= {temp[N-2:0],input};
assign input_dly10 = temp[N-1];
4.边沿检测电路
通过对输入信号进行打两拍进行寄存
input signal;
reg signal_r1;
reg signal_r2;
wire signal_rising;
wire signal_down;
always@(posedge clk or negedge rst)
if(!rst)
signal_r1<= 1'b0;
else
signal_r1<= signal;
always@(posedge clk or negedge rst)
if(!rst)
signal_r2<= 1'b0;
else
signal_r2<= signal_r1;
assign signal_rising = ((signal_r1 == 1'b1)&&(signal_r2 == 1'b0))? 1:0; //检测上升延
assign signal_down = ((signal_r1 == 1'b0)&&(signal_r2 == 1'b1))? 1:0; //检测下降延
//-----------便捷方法如下----------
input signal;
reg [3:0] sig_nsyn_r; //信号异步移位
wire signal_rising;
wire signal_down;
always@(posedge clk or negedge rst)
begin
if(!rst)
sig_nsyn_r <= 4'd0; //检测的信号平时状态为0
//sig_nsyn_r <= 4'b11; //检测的信号平时状态为1
else
sig_nsyn_r <= {sig_nsyn_r[2:0],signal};
end
assign signal_rising = ~sig_nsyn_r[3] & sig_nsyn_r[2];
assign signal_down = sig_nsyn_r[3] & ~sig_nsyn_r[2];
reg 类型变量 加满后自动清零 不需要单独有清零操作
5.曼切斯特编码
module manchester_encoder (
input clk,
input rst,
input enc_in,
output reg q
);
localparam S0 = 2'd0;
localparam S1 = 2'd1;
localparam S2 = 2'd2;
reg [1:0] state ;
reg clk_base;
always @(posedge clk or negedge rst)
begin
if(!rst)
clk_base <= 1'b0;
else
clk_base <= ~clk_base;
end
//状态转换
always @(posedge clk)
begin
if (!rst)
begin
q<= 1'b0;
state <= S0;
end
else
case (state)
S0:
begin
if (clk_base)
state <= S0;
else
if (enc_in)
begin
q<= 1'b1;
state <= S1;
end
else
begin
q<= 1'b0;
state <= S2;
end
end
S1:
begin
q<= 1'b0;
state <= S0;
end
S2:
begin
q<= 1'b1;
state <= S0;
end
default:
state <= S0;
endcase
end
endmodule
tb
module tb_manchester_encoder;
// Parameters
// Ports
reg clk = 0;
reg rst = 0;
reg enc_in = 0;
reg clk_base = 0;
wire q;
manchester_encoder manchester_encoder_dut (
.clk (clk ),
.rst (rst ),
.enc_in (enc_in ),
.q ( q)
);
initial begin
begin
clk = 1;
rst = 0;
clk_base = 1;
enc_in = 0;
#200
rst = 1;
#200
@(posedge clk_base)
enc_in = 1;
@(posedge clk_base)
enc_in = 0;
@(posedge clk_base)
enc_in = 1;
@(posedge clk_base)
enc_in = 0;
#200 $stop;
end
end
always
#10 clk = ! clk ;
always @(posedge clk) clk_base = ~clk_base;
endmodule
6.曼切斯特解码
module manchester_decoder (
input clk,
input rst,
input enc_out,
output reg dec_out
);
localparam S0 = 2'd0;
localparam S1 = 2'd1;
localparam S2 = 2'd2;
reg [1:0] state ;
reg clk_base;
always @(posedge clk or negedge rst)
begin
if(!rst)
clk_base <= 1'b0;
else
clk_base <= ~clk_base;
end
//状态转换
always @(posedge clk)
begin
if (!rst)
begin
dec_out<= 1'b0;
state <= S0;
end
else
case (state)
S0:
begin
if (!clk_base)
state <= S0;
else
if (enc_out)
begin
dec_out<= 1'b1;
state <= S1;
end
else
begin
dec_out<= 1'b0;
state <= S2;
end
end
S1:
state <= S0;
S2:
state <= S0;
default:
state <= S0;
endcase
end
endmodule
7.二进制转格雷码
//二进制转格雷码
module bin2gray
#(
parameter data_width = 'd4 //数据位宽
)
(
input [data_width - 1 : 0] bin , //二进制
output [data_width - 1 : 0] gray //格雷码
);
assign gray = (bin >> 1) ^ bin;
endmodule
8.任意偶分频电路
parameter N = 8; // 16分频
reg clk_div_N;
reg [$clog2(N):0] cnt_dig_N;
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt_dig_N <= 1'b0;
else if(cnt_dig_N == N - 1'd1)
cnt_dig_N <= 1'b0;
else
cnt_dig_N <= cnt_dig_N + 1'd1;
end
always@(posedge clk or negedge rst)
begin
if(!rst)
clk_div_N <= 1'b0;
else if(cnt_dig_N == N - 1'd1)
clk_div_N <= ~clk_div_N;
else
clk_div_N <= clk_div_N;
end