VL33非整数倍数据位宽转换8to12
和上一题一样的,注意valid_out输出时加一个valid_in(其实32题也要加,不过不加仿真也能过)。
`timescale 1ns/1nsmodule 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 [2:0]count;always@(posedge clk or negedge rst_n)begin if(~rst_n) count <= 0; else if(valid_in) count <= (count<2)?count + 1:0;endalways@(posedge clk or negedge rst_n)begin if(~rst_n) valid_out <= 0; else if(valid_in&&(count==1||count==2)) valid_out <= 1; else valid_out <= 0;endreg [11:0]data_lock;always@(posedge clk or negedge rst_n)begin if(~rst_n)begin data_lock <= 0; data_out <= 0; end else if(valid_in)begin data_lock <= {data_lock[3:0],data_in}; if(count == 1) data_out <= {data_lock[7:0],data_in[7:4]}; else if(count == 2) data_out <= {data_lock[3:0],data_in}; endendendmodule
VL34整数倍数据位宽转换8to16
越做越简单了,整数倍位宽转换就非常轻松了。
`timescale 1ns/1nsmodule width_8to16( input clk , input rst_n , input valid_in , input [7:0] data_in , output reg valid_out, output reg [15:0] data_out);reg count;always@(posedge clk or negedge rst_n)begin if(~rst_n) count <= 0; else if(valid_in) count <= count + 1;endalways@(posedge clk or negedge rst_n)begin if(~rst_n) valid_out <= 0; else if(valid_in && count) valid_out <= 1; else valid_out <= 0;endreg [7:0]data_lock;always@(posedge clk or negedge rst_n)begin if(~rst_n)begin data_lock <= 0; data_out <= 0; end else if(valid_in)begin data_lock <= data_in; if(count == 1) data_out <= {data_lock,data_in}; endendendmodule
VL35状态机-非重叠的序列检测
也是一道比较简单的题,不过要注意是非重叠检测,用状态机比用移位寄存器更方便一点。
`timescale 1ns/1nsmodule sequence_test1( input wire clk , input wire rst , input wire data , output reg flag);//*************code***********//reg [2:0]state,next_state;localparam S0=0,S1=1,S2=2,S3=3,S4=4;always@(posedge clk or negedge rst)begin if(~rst) state <= S0; else state <= next_state;endalways@(*)begin case(state) S0:next_state = data ? S1 :S0; S1:next_state = data ? S1 :S2; S2:next_state = data ? S3 :S0; S3:next_state = data ? S4 :S2; S4:next_state = data ? S0 :S2; default:next_state = S0; endcaseendalways@(posedge clk or negedge rst)begin if(~rst) flag <= 0; else if(state == S4 && data) flag <= 1; else flag <= 0;end//*************code***********//endmodule
VL36状态机-重叠序列检测
重叠序列用移位寄存器肯定更方便,不过题目要求用状态机,同样也是注意状态跳变就行了。注意输出延后了一个周期,可以通过加一个状态来实现。
`timescale 1ns/1nsmodule sequence_test2( input wire clk , input wire rst , input wire data , output reg flag);//*************code***********//reg [2:0]state,next_state;localparam S0=0,S1=1,S2=2,S3=3,S4=4;always@(posedge clk or negedge rst)begin if(~rst) state <= S0; else state <= next_state;endalways@(*)begin case(state) S0:next_state = data ? S1 :S0; S1:next_state = data ? S1 :S2; S2:next_state = data ? S3 :S0; S3:next_state = data ? S4 :S2; S4:next_state = data ? S1 :S2; default:next_state = S0; endcaseendalways@(posedge clk or negedge rst)begin if(~rst) flag <= 0; else if(state == S4) flag <= 1; else flag <= 0;end//*************code***********//endmodule
VL37时钟分频(偶数)
一眼行波计数器,不过输出定义的是wire,懒得再去改了。
我这里是组合逻辑输出,其实也不大好。
`timescale 1ns/1nsmodule even_div ( input wire rst , input wire clk_in, output wire clk_out2, output wire clk_out4, output wire clk_out8 );//*************code***********//reg [2:0]count;always@(posedge clk_in or negedge rst)begin if(~rst) count <= 0; else count <= count + 1;endassign clk_out2 = count[0];assign clk_out4 = count[1:0]>0&&count[1:0]<3;assign clk_out8 = count>0&&count<5;//*************code***********//endmodule
VL38自动贩售机1
写完发现题目出的有点垃圾,输入d直接在上升沿给值,下降沿恢复,只有半个周期,晕。
状态机折磨了半天,看了看题解,用计数器确实方便多了,一遍过。
`timescale 1ns/1nsmodule seller1( input wire clk , input wire rst , input wire d1 , input wire d2 , input wire d3 , output reg out1, output reg [1:0]out2);//*************code***********//reg[2:0]count;always@(posedge clk or negedge rst)begin if(~rst)begin count <= 0; out1 <= 0; out2 <= 0; end else begin if(d1) count <= count + 1; else if(d2) count <= count + 2; else if(d3) count <= count + 4; if(count>=3)begin count <= 0; out1 <= 1; out2 <= count -3; end else begin out1 <= 0; out2 <= 0; end endend//*************code***********//endmodule
VL39自动贩售机2
和上一题是一样的,加了一个sel的判断。
`timescale 1ns/1nsmodule seller2( input wire clk , input wire rst , input wire d1 , input wire d2 , input wire sel , output reg out1, output reg out2, output reg out3);//*************code***********//reg [2:0]count;always@(posedge clk or negedge rst)begin if(~rst)begin count <= 0; out1 <= 0; out2 <= 0; out3 <= 0; end else begin if(d1) count <= count + 1; else if(d2) count <= count + 2; if(sel)begin if(count >= 5)begin out1 <= 0; out2 <= 1; out3 <= count - 5; count <= 0; end else begin out1 <= 0; out2 <= 0; out3 <= 0; end end else begin if(count >= 3)begin out1 <= 1; out2 <= 0; out3 <= count - 3; count <= 0; end else begin out1 <= 0; out2 <= 0; out3 <= 0; end end endend//*************code***********//endmodule
VL40占空比50%的奇数分频
用两个计数器,一个上升沿计数,一个下降沿计数即可。
不过感觉题目还是有点问题,第一个下降沿复位还没结束,计数器应该不会累加才对。
`timescale 1ns/1nsmodule odo_div_or ( input wire rst , input wire clk_in, output wire clk_out7 );//*************code***********//reg clk_out1;reg clk_out2;reg [2:0]count1;reg [2:0]count2;always@(posedge clk_in or negedge rst)begin if(~rst)begin count1 <= 0; clk_out1 <= 0; end else begin count1 <= (count1 < 6)?(count1 + 1):0; if(count1 == 3 || count1 ==6) clk_out1 <= ~clk_out1; endendalways@(negedge clk_in or negedge rst)begin if(~rst)begin count2 <= 0; clk_out2 <= 0; end else begin count2 <= (count2 < 6)?(count2 + 1):0; if(count2 == 3 || count2 ==6) clk_out2 <= ~clk_out2; endendassign clk_out7 = clk_out1 | clk_out2;//*************code***********//endmodule
VL41任意小数分频
题目给了明示,要先3次8分频再7次9分频,连时钟切换点都给出来了。
`timescale 1ns/1nsmodule div_M_N( input wire clk_in, input wire rst, output wire clk_out);parameter M_N = 8'd87; parameter c89 = 8'd24; // 8/9时钟切换点parameter div_e = 5'd8; //偶数周期parameter div_o = 5'd9; //奇数周期//*************code***********//reg [6:0]count;reg [3:0]count_e;reg [3:0]count_o;reg clk_MN;always@(posedge clk_in or negedge rst)begin if(~rst) count <= 0; else count <= (count < M_N -1)?(count + 1):0;endalways@(posedge clk_in or negedge rst)begin if(~rst)begin count_e <= 0; count_o <= 0; clk_MN <= 0; end else begin if(count <= c89 - 1)begin count_e <= (count_e < div_e -1)?(count_e + 1):0; if(count_e == 0||count_e == div_e/2) clk_MN <= ~clk_MN; end else begin count_o <= (count_o < div_o -1)?(count_o + 1):0; if(count_o == 0||count_o == (div_o-1)/2) clk_MN <= ~clk_MN; end endendassign clk_out = clk_MN;//*************code***********//endmodule
VL42无占空比要求的奇数分频
说是无占空比要求,其实tb还是要求的50%,无语。参照VL40即可。
写完发现其实要求占空比40%,乌鱼子。
`timescale 1ns/1nsmodule odd_div ( input wire rst , input wire clk_in, output wire clk_out5);//*************code***********//reg [2:0]count;reg clk_div;always@(posedge clk_in or negedge rst)begin if(~rst)begin count <= 0; clk_div <= 0; end else begin count <= (count < 4)?(count + 1):0; if(count == 0 ||count == 2) clk_div <= ~clk_div; endendassign clk_out5 = clk_div;//*************code***********//endmodule
VL43根据状态转移写状态机-三段式
`timescale 1ns/1nsmodule fsm1( input wire clk , input wire rst , input wire data , output reg flag);//*************code***********//reg[1:0]state,next_state;localparam S0=0,S1=1,S2=2,S3=3;always@(posedge clk or negedge rst)begin if(~rst) state <= S0; else state <= next_state;endalways@(*)begin case(state) S0:next_state = data?S1:S0; S1:next_state = data?S2:S1; S2:next_state = data?S3:S2; S3:next_state = data?S0:S3; default:next_state = S0; endcaseendalways@(posedge clk or negedge rst)begin if(~rst) flag <= 0; else begin if(state == S3 && data) flag <= 1; else flag <= 0; endend//*************code***********//endmodule
VL44根据状态转移写状态机-二段式
两段式把输出和状态转移条件写一起,直接通过组合逻辑输出。
`timescale 1ns/1nsmodule fsm2( input wire clk , input wire rst , input wire data , output reg flag);//*************code***********//reg[2:0]state,next_state;localparam S0=0,S1=1,S2=2,S3=3,S4=4;always@(posedge clk or negedge rst)begin if(~rst) state <= S0; else state <= next_state;endalways@(*)begin case(state) S0:begin next_state = data?S1:S0; flag =0; end S1:begin next_state = data?S2:S1; flag =0; end S2:begin next_state = data?S3:S2; flag =0; end S3:begin next_state = data?S4:S3; flag =0; end S4:begin next_state = data?S1:S0; flag = 1; end default:begin next_state = S0; flag =0; end endcaseend//*************code***********//endmodule