VL5 信号发生器
描述
题目描述:
请编写一个信号发生器模块,根据波形选择信号wave_choise发出相应的波形:wave_choice=0时,发出方波信号;wave_choice=1时,发出锯齿波信号;wave_choice=2时,发出三角波信号。
模块的接口信号图如下:
模块的时序图如下:
题意整理
实现不同波形的输出可以使用case语句,以wave_choise作为case语句的cans.根据wave_choise的值输出不同的波形。以0为最低值,20为最高值为例(可以根据需要具体修改)。根据不同波形的需要,产生相应的数据:
方波:产生占空比50%的方波,输出0保持20个时钟,输出20保持20个时钟。
锯齿波:输出数据从0按照步长1递增至20,再从20跳变到0,再依次递增,以此循环。
三角波:输出数据从0按照步长1递增至20,再从20递减到0,以此循环。
题解主体
首先是方波的实现,较为简单,只需要设置一个计数器,使输出保持20个时钟为0,跳变为20,再保持20个时钟。依次循环。可以按照如下的过程实现:cnt每个时钟加一,当cnt=19时,将wave的值置为0,同时cnt置为0;当cnt=9时,将wave的值置为20。
reg [4:0]cnt;
if (cnt == 5'd19)
begin
wave <= 5'd0;
cnt <= 5'd0;
end
else if(cnt == 5'd9)
begin
wave <= 5'd20;
cnt <= cnt + 1'd1;
end
else
begin
wave <= wava;
cnt <= cnt + 1'd1;
end
锯齿波的实现,即输出信号由0每次加一递增到20,然后从20跳变到0。可以按照如下的过程实现:当wave=20,将wave的值置为0,其余时刻,wave加一。
if (wave == 5'd20)
begin
wave <= 5'd0;
end
else
begin
wave <= wava + 1'd1;
end
三角波的实现,类似于锯齿波,但当wave达到20时,不是跳变到0,而是以一为步长递减到0。可以设置一个指示信号up,当up的值是1时,wave每个时钟加一。当up的值为0时,则减一。
if (wave == 5'd20)
begin
wave <= wave - 1'd1;
up = 1'd0;
end
else if (wave = 5'd0)
begin
wave <= wava - 1'd1;
up = 1'd1;
end
else if (up)
begin
wave <= wava + 1'd1;
end
else
begin
wave <= wava - 1'd1;
end
`timescale 1ns/1ns
module signal_generator(
input clk,
input rst_n,
input [1:0] wave_choise,
output reg [4:0]wave
);
reg [4:0]cnt;
reg up;
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
wave <= 5'd0;
cnt <= 5'd0;
end
else case (wave_choise)
2'b00: //产生方波,保持0十个时钟,保持20十个时钟
begin
if (cnt == 5'd19)
begin
wave <= 5'd0;
cnt <= 5'd0;
end
else if(cnt == 5'd9)
begin
wave <= 5'd20;
cnt <= cnt + 1'd1;
end
else
begin
wave <= wave;
cnt <= cnt + 1'd1;
end
end
2'b01: //产生锯齿,0递增到20
begin
if (wave == 5'd20)
begin
wave <= 5'd0;
end
else
begin
wave <= wave + 1'd1;
end
end
2'b10:
begin
if (wave == 5'd20)
begin
wave <= wave - 1'd1;
up = 1'd0;
end
else if (wave == 5'd0)
begin
wave <= wave - 1'd1;
up = 1'd1;
end
if (up)
begin
wave <= wave + 1'd1;
end
else
begin
wave <= wave - 1'd1;
end
end
default:
begin
wave <= 1'b0;
end
endcase
endmodule
VL6 数据串转并电路 ***
描述
实现串并转换电路,输入端输入单bit数据,每当本模块接收到6个输入数据后,输出端输出拼接后的6bit数据。本模块输入端与上游的采用valid-ready双向握手机制,输出端与下游采用valid-only握手机制。数据拼接时先接收到的数据放到data_b的低位。
电路的接口如下图所示。valid_a用来指示数据输入data_a的有效性,valid_b用来指示数据输出data_b的有效性;ready_a用来指示本模块是否准备好接收上游数据,本模块中一直拉高;clk是时钟信号;rst_n是异步复位信号。
接口时序示意图
题意整理
本题要求实现将6个单bit输入数据拼接之后输出。
时序图含有的信息较多,观察时序图需要注意:
l data_b是在已接收到6个数据后下一个时钟产生输出;
l 本模块与上游采用valid_ready握手机制,当valid_a拉低,表示与上游握手未成功,则此时data_a的数据无效,不存入本模块当中;
l 本模块与下游采用valid_only握手机制,这是一种单向指示性握手机制,已接收到6个数据后,valid_b拉高一个时钟周期,指示输出数据有效性
题解主体
要实现6个单bit输入数据的拼接,要用1个寄存器将先到达的数据缓存。当上游握手成功,将输入数据进寄存器,先收到的数据放在低位;当缓存好6个输入数据,valid_b拉高,输出data_b。
需要计数器来计数接收到的数据数量,计数器在0-5之间循环。计数器初始值是0,每接收一个数据,计数器加1,当计数器再次循环到0时,表示已经接收到6个数据,可以输出拼接结果。
Verilog代码如下:
reg [5:0] data_reg;
reg [2:0] data_cnt;
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
ready_a <= 'd0;
else
ready_a <= 1'd1;
end
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
data_cnt <= 'd0;
else if(valid_a && ready_a)
data_cnt <= (data_cnt == 3'd5) ? 'd0 : (data_cnt + 1'd1);
end
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
data_reg <= 'd0;
else if(valid_a && ready_a)
data_reg <= {data_a, data_reg[5:1]};
end
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)begin
valid_b <= 'd0;
data_b <= 'd0;
end
else if(data_cnt == 3'd5)begin
valid_b <= 1'd1;
data_b <= {data_a, data_reg[5:1]};
end
else
valid_b <= 'd0;
end
VL7 数据累加输出***
描述
实现串行输入数据累加输出,输入端输入8bit数据,每当模块接收到4个输入数据后,输出端输出4个接收到数据的累加结果。输入端和输出端与上下游的交互采用valid-ready双向握手机制。要求上下游均能满速传输时,数据传输无气泡,不能由于本模块的设计原因产生额外的性能损失。
电路的接口如下图所示。valid_a用来指示数据输入data_in的有效性,valid_b用来指示数据输出data_out的有效性;ready_a用来指示本模块是否准备好接收上游数据,ready_b表示下游是否准备好接收本模块的输出数据;clk是时钟信号;rst_n是异步复位信号。
接口时序示意图
输入描述:
input clk ,
input rst_n ,
input [7:0] data_in ,
input valid_a ,
input ready_b
输出描述:
output ready_a ,
output reg valid_b ,
output reg [9:0] data_out
题意整理
本题要求实现将4个输入数据累加之后输出,模块与上下游采用valid-ready双向握手机制。