题目描述:
请编写一个信号发生器模块,根据波形选择信号wave_choise发出相应的波形:wave_choice=0时,发出方波信号;wave_choice=1时,发出锯齿波信号;wave_choice=2时,发出三角波信号。
2.1 时序逻辑的题目使用状态机。
2.2 三角波模式需要设置一个标志位flag
。flag
仅在三角波模式也就是wave_chosie==2
时工作。当flag==0
时,wave
减少;当flag==1
时,wave
增加。
`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 flag;
// 方波模式下,计数器控制
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= wave_choise!=0 ? 0:
cnt ==19? 0:
cnt + 1;
end
// 三角波模式下,标志位控制
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
flag <= 0;
else
flag <= wave_choise!=2 ? 0:
wave ==1 ? 1:
wave ==19? 0:
flag;
end
// 更新wave信号
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
wave <= 0;
else
case(wave_choise)
0 : wave <= cnt == 9? 20 :
cnt ==19? 0 :
wave;
1 : wave <= wave==20? 0 : wave+1;
2 : wave <= flag==0 ? wave-1: wave+1;
default: wave <= 0;
endcase
end
endmodule
实现串并转换电路,输入端输入单bit数据,每当本模块接收到6个输入数据后,输出端输出拼接后的6bit数据。本模块输入端与上游的采用valid-ready双向握手机制,输出端与下游采用valid-only握手机制。数据拼接时先接收到的数据放到data_b的低位。
电路的接口如下图所示。valid_a用来指示数据输入data_a的有效性,valid_b用来指示数据输出data_b的有效性;ready_a用来指示本模块是否准备好接收上游数据,本模块中一直拉高;clk是时钟信号;rst_n是异步复位信号。
2.1注意开始的时候 和复位 的时候 ready_a = 0; 就行。
`timescale 1ns/1ns
module s_to_p(
input clk ,
input rst_n ,
input valid_a ,
input data_a ,
output reg ready_a ,
output reg valid_b ,
output reg [5:0] data_b
);
reg[5:0] data;// Data buffer 数据缓存区
reg[3:0] cnt;// counter 计数器
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
data_b <=6'b0;
valid_b <=1'b0;
ready_a <=1'b0;
cnt <=0;
end
else
begin
ready_a <=1'b1;
if(valid_a == 1'b1)
begin
cnt <= cnt +1;
data <= {data_a , data[5:1]};
valid_b <= 1'b0;
if(cnt == 3'd5)
begin
cnt <=0;
data_b <= {data_a,data[5:1]};
valid_b <=1'b1;
end
end
end
end
endmodule
实现串行输入数据累加输出,输入端输入8bit数据,每当模块接收到4个输入数据后,输出端输出4个接收到数据的累加结果。输入端和输出端与上下游的交互采用valid-ready双向握手机制。要求上下游均能满速传输时,数据传输无气泡,不能由于本模块的设计原因产生额外的性能损失。
电路的接口如下图所示。valid_a用来指示数据输入data_in的有效性,valid_b用来指示数据输出data_out的有效性;ready_a用来指示本模块是否准备好接收上游数据,ready_b表示下游是否准备好接收本模块的输出数据;clk是时钟信号;rst_n是异步复位信号。
2.1 时序逻辑 采用状态机。
2.1 这个题目要注意看细节, 就是计数的条件 和各个 变量 变化的条件。
①ready_a:为高表示我现在没啥事,告诉上游我准备好了,你可以发数据了;
②valid_b:为高表示给下游说我发数据了;
③data_out:给下游发的数据,配合valid_b,只有valid_b为高时,发送的才是有效数据。
那么分别来处理:
①ready_a: 如果下游ready_b拉高,表示下游可以接收模块输出数据,那么此时ready_a应拉高;同时,如果valid_b为低,表示4个数据还没收完,所以也拉高继续接收。
②valid_b: 当和上游正常通讯时(即valid_a和ready_a均为高),数据正常接收,但注意计数了4个就得加起来输出一次,所以data_cnt == 2'd3时拉高valid_b;而等待下游接收,即当ready_a也拉高表示接收完成,则拉低valid_b,保证只有在四个数之和的时候才拉高。
③data_out: 同理,当和上游正常通讯时(即valid_a和ready_a均为高),数据正常接收,数据累加,当计数器data_cnt == 2'd0表示需要从头再加,清零,但注意需要等到ready_b拉高,表示下游接收完成才能清空重新累加。
`timescale 1ns/1ns
module valid_ready(
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
);
assign ready_a = ready_b | ~valid_b;
reg [1:0] data_cnt;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
data_cnt <= 2'd0;
else if(valid_a && ready_a)
data_cnt <= data_cnt +2'd1;
else
data_cnt <= data_cnt;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
valid_b <= 1'b0;
else if(valid_a && ready_a && data_cnt == 2'd3)
valid_b <= 1'd1;
else if(valid_b && ready_b)
valid_b <= 1'd0;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
data_out <= 10'b0;
else if(valid_a && ready_a && data_cnt == 2'd0 && ready_b) //这里要接收的时候才清零
data_out <= data_in; //相当于清零,重新累加
else if(valid_a && ready_a)
data_out <= data_out + data_in;
end
endmodule
实现数据位宽转换电路,实现24bit数据输入转换为128bit数据输出。其中,先到的数据应置于输出的高bit位。
电路的接口如下图所示。valid_in用来指示数据输入data_in的有效性,valid_out用来指示数据输出data_out的有效性;clk是时钟信号;rst_n是异步复位信号。
2.1 定义一个可以存储 128 位的寄存器。
2.2列出 计数器 对应的每个信号的位数。 (简单,看得出)
2.3 使用状态机来作, 主要是 15个状态。 因为 24 *16 = 128 *3
`timescale 1ns/1ns
module width_24to128(
input clk ,
input rst_n ,
input valid_in ,
input [23:0] data_in ,
output reg valid_out ,
output reg [127:0] data_out
);
reg[128:0] data;//data duffer //128 x3 = 24 *16
reg[3:0] cnt;// counter 16个状态
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
cnt <=0;
data <=0;
end
else
begin
if(cnt == 4'd0 && valid_in == 1'd1)
begin
cnt <= cnt+1;
data <= data_in;
end
else if(cnt == 4'd15 && valid_in == 1'd1)
begin
cnt <= 0;
data <={data[119:0],data_in};
end
else if(valid_in == 1'd1)
begin
cnt <= cnt +1;
data <= {data[119:0],data_in};
end
end
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
valid_out <=0;
data_out <=0;
end
else
begin
if(cnt == 4'd5)
begin
data_out <= {data[119:0],data_in[23:16]};
valid_out <=1;
end
else if(cnt == 4'd10)
begin
data_out <= {data[111:0],data_in[23:8]};
valid_out <=1;
end
else if(cnt == 4'd15)
begin
data_out <= {data[103:0],data_in[23:0]};
valid_out <=1;
end
else
begin
valid_out <=0;
data_out <= data_out;
end
end
end
endmodule