03 时序逻辑
VL21 根据状态转移表实现时序电路
`timescale 1ns/1ns module seq_circuit( input A , input clk , input rst_n, output wire Y ); reg q0,q1; always@(posedge clk or negedge rst_n) begin if(~rst_n) begin q1 <= 0; end else begin; q1 <= (~A)&(~q1)&(q0) | (~A)&(q1)&(~q0) | (A)&(~q1)&(~q0) | (A)&(q1)&(q0); end end always@(posedge clk or negedge rst_n) begin if(~rst_n) begin q0 <= 0; end else begin; q0 <= ~q0; end end assign Y = q0 & q1; endmodule
VL22 根据状态转移图实现时序电路
`timescale 1ns/1ns module seq_circuit( input C , input clk , input rst_n, output wire Y ); //定义的状态类型 parameter IDLE = 2'b00 ; parameter GET1 = 2'b01 ; parameter GET2 = 2'b10 ; parameter GET3 = 2'b11 ; //machine variable reg [1:0] st_next ; reg [1:0] st_cur ; //(1) state transfer always @(posedge clk or negedge rst_n) begin if (!rst_n) begin st_cur <= IDLE ; end else begin st_cur <= st_next ; end end always @(*) begin case (st_cur) IDLE:begin if (C == 0) begin st_next <= IDLE; end else begin st_next <= GET1; end end GET1:begin if (C == 1) begin st_next <= GET1; end else begin st_next <= GET3; end end GET3:begin if (C == 0) begin st_next <= GET3; end else begin st_next <= GET2; end end GET2:begin if (C == 1) begin st_next <= GET2; end else begin st_next <= IDLE; end end default:st_next <= IDLE; endcase end reg Y_tmp; always@(*) begin case (st_cur) IDLE:begin Y_tmp <= 1'b0; end GET1:begin Y_tmp <= 1'b0; end GET2:begin if (C == 1) begin Y_tmp <= 1'b1; end else begin Y_tmp <= 1'b0; end end GET3:begin if (C == 0) begin Y_tmp <= 1'b1; end end default: Y_tmp <= 1'b0; endcase end assign Y = Y_tmp; endmodule
VL23 ROM的简单实现
`timescale 1ns/1ns module rom( input clk, input rst_n, input [7:0]addr, output [3:0]data ); //开辟一个深度为8,位宽为4的空间 reg [3:0] rom_data [7:0]; assign data = rom_data[addr]; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rom_data[0] <= 4'd0; rom_data[1] <= 4'd2; rom_data[2] <= 4'd4; rom_data[3] <= 4'd6; rom_data[4] <= 4'd8; rom_data[5] <= 4'd10; rom_data[6] <= 4'd12; rom_data[7] <= 4'd14; end else begin rom_data[0] <= 4'd0; rom_data[1] <= 4'd2; rom_data[2] <= 4'd4; rom_data[3] <= 4'd6; rom_data[4] <= 4'd8; rom_data[5] <= 4'd10; rom_data[6] <= 4'd12; rom_data[7] <= 4'd14; end end endmodule
VL24 边沿检测
`timescale 1ns/1ns module edge_detect( input clk, input rst_n, input a, output reg rise, output reg down ); reg a_tep; always @(posedge clk or negedge rst_n) begin if(~rst_n) begin a_tep <= 1'b0; end else begin a_tep <= a; end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin rise <= 1'b0; down <= 1'b0; end else begin if (a & ~a_tep) begin rise <= 1'b1; down <= 1'b0; end else if (~a & a_tep) begin rise <= 1'b0; down <= 1'b1; end else begin rise <= 1'b0; down <= 1'b0; end end end endmodule
2 Verilog进阶挑战
01 序列检测
VL25 输入序列连续的序列检测
`timescale 1ns/1ns module sequence_detect( input clk, input rst_n, input a, output reg match ); reg [7:0] state_cache; always @(posedge clk or negedge rst_n) begin if(~rst_n) begin state_cache <= 8'b0; match <= 1'b0; end else begin state_cache <= {state_cache[6:0],a}; if (state_cache == 8'b0111_0001) begin match <= 1'b1; end else begin match <= 1'b0; end end end endmodule
VL26 含有无关项的序列检测
`timescale 1ns/1ns module sequence_detect( input clk, input rst_n, input a, output reg match ); reg [8:0] state_cache; always @(posedge clk or negedge rst_n) begin if(~rst_n) begin state_cache <= 8'b0; match <= 1'b0; end else begin state_cache <= {state_cache[7:0],a}; if (state_cache[8:6] == 3'b011 && state_cache[2:0] == 3'b110) begin match <= 1'b1; end else begin match <= 1'b0; end end end endmodule
VL27 不重叠序列检测
`timescale 1ns/1ns module sequence_detect( input clk, input rst_n, input data, output reg match, output reg not_match ); //定义的状态类型 parameter IDLE = 4'd0 ; parameter s1 = 4'd1 ; parameter s2 = 4'd2 ; parameter s3 = 4'd3 ; parameter s4 = 4'd4 ; parameter s5 = 4'd5 ; parameter s6 = 4'd6 ; parameter sf1 = 4'd7 ; parameter sf2 = 4'd8 ; parameter sf3 = 4'd9 ; parameter sf4 = 4'd10 ; parameter sf5 = 4'd11 ; parameter sf6 = 4'd12 ; //machine variable reg [ 3:0] st_next ; reg [ 3:0] st_cur ; //(1) state transfer always @(posedge clk or negedge rst_n) begin if (!rst_n) begin st_cur <= IDLE ; end else begin st_cur <= st_next ; end end always@(st_cur or data) begin case (st_cur) IDLE:begin if(data == 0) begin st_next = s1; end else begin st_next = sf1; end end s1:begin if(data == 1) begin st_next = s2; end else begin st_next = sf2; end end s2:begin if(data == 1) begin st_next = s3; end else begin st_next = sf3; end end s3:begin if(data == 1) begin st_next = s4; end else begin st_next = sf4; end end s4:begin if(data == 0) begin st_next = s5; end else begin st_next = sf5; end end s5:begin if(data == 0) begin st_next = s6; end else begin st_next = sf6; end end s6:begin if(data == 0) begin st_next = s1; end else begin st_next = sf1; end end sf1:begin st_next = sf2; end sf2:begin st_next <= sf3; end sf3:begin st_next = sf4; end sf4:begin st_next = sf5; end sf5:begin st_next = sf6; end sf6:begin if (data == 0) begin st_next = s1; end else begin st_next = sf1; end end default: st_next = IDLE; endcase end always @(*) begin if (!rst_n) begin match <= 1'b0; not_match <= 1'b0; end else begin if(st_cur == s6) begin match <= 1'b1; not_match <= 1'b0; end else if(st_cur == sf6) begin match <= 1'b0; not_match <= 1'b1; end else begin match <= 1'b0; not_match <= 1'b0; end end end endmodule
VL28 输入序列不连续的序列检测
`timescale 1ns/1ns module sequence_detect( input clk , input rst_n , input data , input data_valid , output reg match ); //定义的状态类型 parameter IDLE = 4'd0 ; parameter s1_0 = 4'd1 ; parameter s2_01 = 4'd2 ; parameter s3_011 = 4'd3 ; parameter s4_0110 = 4'd4 ; //machine variable reg [ 3:0] st_next ; reg [ 3:0] st_cur ; //(1) state transfer always @(posedge clk or negedge rst_n) begin if (!rst_n) begin st_cur <= IDLE ; end else begin st_cur <= st_next ; end end always @(st_cur or data or data_valid) begin case (st_cur) IDLE:begin if(data_valid && data == 0) begin st_next = s1_0; end else begin st_next = IDLE; end end s1_0:begin if(data_valid) begin if (data == 1) begin st_next = s2_01; end else begin st_next = s1_0; end end else begin st_next = s1_0; end end s2_01:begin if(data_valid) begin if (data == 1) begin st_next = s3_011; end else begin st_next = s1_0; end end else begin st_next = s2_01; end end s3_011:begin if(data_valid) begin if (data == 0) begin st_next = s4_0110; end else begin st_next = IDLE; end end else begin st_next = s3_011; end end s4_0110:begin if(data_valid) begin if (data == 0) begin st_next = s1_0; end else begin st_next = IDLE; end end else begin st_next = IDLE; end end default: st_next = IDLE; endcase end always @(st_cur or rst_n) begin if(!rst_n==1) begin match <= 1'b0; end else if (st_cur == s4_0110) begin match <= 1'b1; end else begin match <= 1'b0; end end endmodule
02 时序逻辑
VL29 信号发生器
`timescale 1ns/1ns module signal_generator( input clk, input rst_n, input [1:0] wave_choise, output reg [4:0]wave ); endmodule
VL30 数据串转并电路
`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_cache ;//数据缓存 reg [ 2:0] data_cnt ;//计数器 //计数器 值如果有效加1; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin data_cnt <= 3'b0; end else begin if(valid_a) begin if(data_cnt == 3'd5) begin data_cnt <= 0; end else begin data_cnt <= data_cnt + 1; end end else begin data_cnt <= data_cnt; end end end //有效赋值 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin data_cache <= 6'b00_0000; end else if(valid_a && data_cnt <= 3'd5) begin data_cache <= {data_a,data_cache[5:1]}; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin data_b <= 6'd0; end else if(data_cnt == 3'd5) begin data_b <= {data_a,data_cache[5:1]}; end else begin data_b <= data_b; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin valid_b <= 1'b0; end else if (data_cnt == 3'd5) begin valid_b <= 1'd1; end else begin valid_b <= 1'd0; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin ready_a <= 1'd0; end else begin ready_a <= 1'd1; end end endmodule
VL31 数据累加输出
`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 ); reg [ 1:0] data_cnt ; //计数器用于表示计算是否满 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin data_cnt <= 2'b0; end else begin if(valid_a && ready_a) begin if(data_cnt == 2'd3) begin data_cnt <= 0; end else begin data_cnt <= data_cnt + 1; end end else begin data_cnt <= data_cnt; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_out <= 10'd0; end else if(valid_a && ready_a) begin if(data_cnt == 2'd0) begin data_out <= data_in; end else begin data_out <= data_out + data_in; end end else begin data_out <= data_out; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin valid_b <= 1'b0; end else begin if(data_cnt == 2'd3 && valid_a && ready_a) begin valid_b <= 1'b1; end else if (valid_b && ready_b) begin valid_b <= 1'b0; end else begin valid_b <= valid_b; end end end assign ready_a = ~valid_b | ready_b; endmodule
VL32 非整数倍数据位宽转换24to128
`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 [3:0] data_cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_cnt <= 3'd0; end else begin if(valid_in) begin if(data_cnt == 4'd15) begin data_cnt <= 4'd0; end else begin data_cnt <= data_cnt + 1'd1; end end else begin data_cnt <= data_cnt; end end end reg [120-1:0] data_buff; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_buff <= 120'd0; end else if(valid_in) begin data_buff <= {data_buff[95:0],data_in}; end else begin data_buff <= data_buff; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_out <= 128'd0; valid_out <= 1'd0; end else begin if(valid_in && data_cnt == 4'd5) begin data_out <= {data_buff,data_in[23:16]}; valid_out <= 1'd1; end else if(valid_in && data_cnt == 4'd10) begin data_out <= {data_buff[111:0],data_in[23:8]}; valid_out <= 1'd1; end else if(valid_in && data_cnt == 4'd15) begin data_out <= {data_buff[103:0],data_in}; valid_out <= 1'd1; end else begin valid_out <= 1'd0; end end end endmodule
VL33 非整数倍数据位宽转换8to12
`timescale 1ns/1ns /* valid_in表示输入有效,当为1表示输入有效,当为0上表述输入数据无效 */ module width_8to12( input clk , input rst_n , input valid_in , input [ 7:0] data_in , output reg valid_out , output reg [ 11:0] data_out ); reg [1:0] data_cnt ; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_cnt <= 2'b0; end else begin if (valid_in) begin if (data_cnt == 2'd2) begin data_cnt <= 2'd0; end else begin data_cnt <= data_cnt + 1'd1; end end else begin data_cnt <= data_cnt; end end end reg [ 7:0] data_buff ; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_buff <= 8'd0; end else begin if (valid_in) begin data_buff <= data_in; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_out <= 12'd0; valid_out <= 1'd0; end else begin if(data_cnt == 2'd1 && valid_in) begin data_out <= {data_buff,data_in[7:4]}; valid_out <= 1'd1; end else if(data_cnt == 2'd2 && valid_in) begin data_out <= {data_buff[3:0],data_in}; valid_out <= 1'd1; end else begin valid_out <= 1'd0; end end end endmodule